#include "backendservice.h"
#include "databasemanager.h"
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QHttpMultiPart>
#include <QHttpPart>
#include <QJsonObject>
#include <QJsonDocument>
#include <QJsonArray>
#include <QDebug>
#include <QUrl>
#include <QUrlQuery>
#include <QByteArray>
#include <QFile>
#include <QFileInfo>
#include <QDir>
#include <QStandardPaths>
#include <QProcess>
#include <QDesktopServices>
#include <QDateTime>
#include <QRandomGenerator>
#include <QRegularExpression>
#include <QFileDialog>
#include <QUuid>
#include <QCryptographicHash>

BackendService::BackendService(QObject *parent)
    : QObject(parent)
    , m_networkManager(new QNetworkAccessManager(this))
    , m_baseUrl("http://localhost:8888") // 默认API地址，可以根据需要修改
    , m_databaseManager(nullptr)
{
    // 连接网络请求完成信号 - 使用lambda表达式直接传递reply
    connect(m_networkManager, &QNetworkAccessManager::finished,
            this, [this](QNetworkReply *reply) {
                qDebug() << "网络请求完成，reply对象:" << reply;
                if (reply) {
                    QString requestType = reply->property("requestType").toString();
                    if (requestType == "login") {
                        handleLoginResponse(reply);
                    } else if (requestType == "syncDisks") {
                        handleSyncDisksResponse(reply);
                    } else if (requestType == "syncFolders") {
                        handleSyncFoldersResponse(reply);
                    } else if (requestType == "syncFiles") {
                        handleSyncFilesResponse(reply);
                    } else if (requestType == "exchangeAccessToken") {
                        handleExchangeAccessTokenResponse(reply);
                    } else if (requestType == "downloadFile") {
                        handleDownloadFileResponse(reply);
                    } else if (requestType == "downloadFileByURL") {
                        handleDownloadFileByURLResponse(reply);
                    } else if (requestType == "rollbackFile") {
                        handleRollbackFileResponse(reply);
                    } else if (requestType == "commitFile") {
                        handleCommitFileResponse(reply);
                    } else if (requestType == "getApplications") {
                        handleGetApplicationsResponse(reply);
                    } else if (requestType == "getNotice") {
                        handleGetNoticeResponse(reply);
                    } else if (requestType == "markReadNotice") {
                        handleMarkReadNoticeResponse(reply);
                    } else if (requestType == "getKmsFileByFileId") {
                        handleGetKmsFileResponse(reply);
                    }
                    reply->deleteLater();
                }
            });
}

BackendService::~BackendService()
{
}

void BackendService::setDatabaseManager(DatabaseManager *databaseManager)
{
    m_databaseManager = databaseManager;
}

DatabaseManager* BackendService::getDatabaseManager() const
{
    return m_databaseManager;
}

void BackendService::loginCheckin(const QString &username, const QString &password, const QString &checkcode)
{
    // 保存当前登录用户名
    m_currentUsername = username;
    
    // 构建请求URL
    QString url = m_baseUrl + "/signon/api/runtime/login/checkin";
    
    // 对密码进行base64编码
    QString encodedPassword = QString::fromUtf8(password.toUtf8().toBase64());
    
    // 将最后2位移到最前面
    if (encodedPassword.length() > 2) {
        QString lp = encodedPassword.left(2);
        QString rp = encodedPassword.right(encodedPassword.length() - 2);
        encodedPassword = rp+lp;
    }
    
    qDebug() << "原始密码:" << password;
    qDebug() << "Base64编码后:" << QString::fromUtf8(password.toUtf8().toBase64());
    qDebug() << "最后2位移到前面后:" << encodedPassword;
    
    // 构建请求体
    QJsonObject requestBody;
    requestBody["username"] = username;
    requestBody["password"] = encodedPassword;
    requestBody["checkcode"] = checkcode;
    
    QJsonDocument doc(requestBody);
    QByteArray data = doc.toJson();
    
    // 创建网络请求
    QNetworkRequest request;
    request.setUrl(QUrl(url));
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
    request.setHeader(QNetworkRequest::ContentLengthHeader, data.size());
    
    qDebug() << "发送登录请求到:" << url;
    qDebug() << "请求体:" << data;
    
    // 发送POST请求
    QNetworkReply *reply = m_networkManager->post(request, data);
    qDebug() << "发送请求，reply对象:" << reply;
    
    // 设置用户数据，用于识别请求类型
    reply->setProperty("requestType", "login");
}


void BackendService::handleLoginResponse(QNetworkReply *reply)
{
    // 打印reply详细信息
    qDebug() << "收到服务器响应，reply对象:" << reply;
    qDebug() << "响应状态码:" << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
    qDebug() << "响应头信息:" << reply->rawHeaderPairs();
    
    // 检查网络错误
    if (reply->error() != QNetworkReply::NoError) {
        qDebug() << "网络请求错误:" << reply->errorString();
        emit loginResult(-1, "网络请求失败: " + reply->errorString(), QStringList());
        return;
    }
    
    // 提取并保存token
    QByteArray setCookieHeader = reply->rawHeader("set-cookie");
    if (!setCookieHeader.isEmpty()) {
        QString setCookieStr = QString::fromUtf8(setCookieHeader);
        qDebug() << "收到set-cookie头:" << setCookieStr;
        
        // 解析checkInToken
        if (setCookieStr.contains("checkInToken=")) {
            int startPos = setCookieStr.indexOf("checkInToken=") + 13; // "checkInToken="的长度
            int endPos = setCookieStr.indexOf(";", startPos);
            if (endPos == -1) {
                endPos = setCookieStr.length();
            }
            QString checkInToken = setCookieStr.mid(startPos, endPos - startPos);
            qDebug() << "提取到checkInToken:" << checkInToken;
            
            // 保存token
            saveToken(checkInToken);
        }
    }
    
    // 读取响应数据
    QByteArray responseData = reply->readAll();
    qDebug() << "登录响应数据包:" << responseData;
    qDebug() << "响应数据长度:" << responseData.size() << "字节";
    
    // 解析JSON响应
    QJsonParseError parseError;
    QJsonDocument doc = QJsonDocument::fromJson(responseData, &parseError);
    
    if (parseError.error != QJsonParseError::NoError) {
        qDebug() << "JSON解析错误:" << parseError.errorString();
        emit loginResult(-2, "响应数据格式错误", QStringList());
        return;
    }
    
    if (!doc.isObject()) {
        qDebug() << "响应数据不是有效的JSON对象";
        emit loginResult(-3, "响应数据格式错误", QStringList());
        return;
    }
    
    QJsonObject response = doc.object();
    parseLoginResponse(response, m_currentUsername);
}

void BackendService::parseLoginResponse(const QJsonObject &response, const QString &username)
{
    // 解析响应字段
    int resultCode = response["resultCode"].toInt();
    QString message = response["msg"].toString();
    QStringList domains;
    
    // 解析domains数组
    if (response.contains("domains") && response["domains"].isArray()) {
        QJsonArray domainsArray = response["domains"].toArray();
        
        // 保存完整的domains信息
        saveDomains(domainsArray);
        
        // 同时构建简化的domains列表用于信号传递
        for (const QJsonValue &value : domainsArray) {
            if (value.isObject()) {
                QJsonObject domain = value.toObject();
                QString domainId = domain["id"].toString();
                QString domainName = domain["name"].toString();
                domains << QString("%1:%2").arg(domainId, domainName);
            }
        }
    }
    
    qDebug() << "登录结果 - 代码:" << resultCode << "消息:" << message << "域名数量:" << domains.size();
    
    // 如果登录成功，创建用户工作目录并同步网盘
    if (resultCode == 0) {
        QString workDirectory = createUserWorkDirectory(username);
        if (!workDirectory.isEmpty()) {
            emit userWorkDirectoryCreated(username, workDirectory);
        }
        
        // 登录成功后同步网盘
        qDebug() << "登录成功，开始同步网盘";
        syncDisks();
    }
    
    // 发送登录结果信号
    emit loginResult(resultCode, message, domains);
}

QString BackendService::createUserWorkDirectory(const QString &username)
{
    // 获取用户主目录
    QString homePath = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
    if (homePath.isEmpty()) {
        qDebug() << "无法获取用户主目录";
        return QString();
    }
    
    // 构建用户工作目录路径
    QString workDirectory = QDir(homePath).filePath(".myapps/" + username);
    
    // 创建目录
    QDir dir;
    if (!dir.exists(workDirectory)) {
        if (dir.mkpath(workDirectory)) {
            qDebug() << "成功创建用户工作目录:" << workDirectory;
        } else {
            qDebug() << "创建用户工作目录失败:" << workDirectory;
            return QString();
        }
    } else {
        qDebug() << "用户工作目录已存在:" << workDirectory;
    }
    
    return workDirectory;
}

void BackendService::saveLoginInfo(const QString &username, const QString &password)
{
    // 获取用户主目录
    QString homePath = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
    if (homePath.isEmpty()) {
        qDebug() << "无法获取用户主目录，无法保存登录信息";
        return;
    }
    
    // 构建设置文件路径
    QString settingsPath = QDir(homePath).filePath(".myapps/setting.ini");
    
    // 确保目录存在
    QDir dir;
    QString settingsDir = QFileInfo(settingsPath).absolutePath();
    if (!dir.exists(settingsDir)) {
        if (!dir.mkpath(settingsDir)) {
            qDebug() << "无法创建设置目录:" << settingsDir;
            return;
        }
    }
    
    // 保存设置
    QSettings settings(settingsPath, QSettings::IniFormat);
    settings.setValue("Login/Username", username);
    settings.setValue("Login/Password", password);
    settings.setValue("Login/RememberPassword", true);
    
    qDebug() << "登录信息已保存到:" << settingsPath;
    qDebug() << "用户名:" << username;
}

QStringList BackendService::loadLoginInfo()
{
    QStringList result;
    
    // 获取用户主目录
    QString homePath = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
    if (homePath.isEmpty()) {
        qDebug() << "无法获取用户主目录，无法读取登录信息";
        return result;
    }
    
    // 构建设置文件路径
    QString settingsPath = QDir(homePath).filePath(".myapps/setting.ini");
    
    // 检查文件是否存在
    if (!QFile::exists(settingsPath)) {
        qDebug() << "设置文件不存在:" << settingsPath;
        return result;
    }
    
    // 读取设置
    QSettings settings(settingsPath, QSettings::IniFormat);
    QString username = settings.value("Login/Username", "").toString();
    QString password = settings.value("Login/Password", "").toString();
    bool rememberPassword = settings.value("Login/RememberPassword", false).toBool();
    
    if (rememberPassword && !username.isEmpty() && !password.isEmpty()) {
        result << username << password;
        qDebug() << "从设置文件读取登录信息:" << settingsPath;
        qDebug() << "用户名:" << username;
    } else {
        qDebug() << "设置文件中没有有效的登录信息";
    }
    
    return result;
}

void BackendService::insertTestFolderData()
{
    qDebug() << "=== 开始插入测试文件夹数据 ===";
    
    // 这里需要访问DatabaseManager，但BackendService没有直接的访问权限
    // 我们可以通过信号来通知主程序插入测试数据
    qDebug() << "BackendService::insertTestFolderData 被调用";
    qDebug() << "=== 测试文件夹数据插入完成 ===";
}

void BackendService::syncDisks()
{
    // 检查是否有accessToken，如果没有则先获取
    if (m_accessToken.isEmpty()) {
        // 获取当前选中的公司ID
        QString companyId = loadSelectedCompanyId();
        if (!companyId.isEmpty()) {
            qDebug() << "没有accessToken，先获取accessToken，公司ID:" << companyId;
            m_pendingSyncDiskId = ""; // 设置为空表示要同步网盘
            ensureAccessToken(companyId);
            // 注意：这里不能立即发送请求，因为ensureAccessToken是异步的
            // 需要在exchangeAccessTokenCompleted信号中重新调用syncDisks
            return;
        } else {
            qDebug() << "没有选中的公司ID，无法获取accessToken";
            emit syncDisksCompleted(-1, "没有选中的公司ID，无法获取accessToken");
            return;
        }
    }
    
    // 构建请求URL
    QString url = m_baseUrl + "/kms/api/kms/sync/disks";
    
    qDebug() << "发送同步网盘请求到:" << url;
    
    // 创建网络请求
    QNetworkRequest request;
    request.setUrl(QUrl(url));
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
    
    // 添加token到请求头
    addTokenToRequest(request);
    
    // 发送GET请求
    QNetworkReply *reply = m_networkManager->get(request);
    qDebug() << "发送同步网盘请求，reply对象:" << reply;
    
    // 设置用户数据，用于识别请求类型
    reply->setProperty("requestType", "syncDisks");
}

void BackendService::handleSyncDisksResponse(QNetworkReply *reply)
{
    // 打印reply详细信息
    qDebug() << "收到同步网盘响应，reply对象:" << reply;
    qDebug() << "响应状态码:" << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
    qDebug() << "响应头信息:" << reply->rawHeaderPairs();
    
    // 检查网络错误
    if (reply->error() != QNetworkReply::NoError) {
        qDebug() << "同步网盘网络请求错误:" << reply->errorString();
        emit syncDisksCompleted(-1, "网络请求失败: " + reply->errorString());
        return;
    }
    
    // 读取响应数据
    QByteArray responseData = reply->readAll();
    qDebug() << "同步网盘响应数据包:" << responseData;
    qDebug() << "响应数据长度:" << responseData.size() << "字节";
    
    // 解析JSON响应
    QJsonParseError parseError;
    QJsonDocument doc = QJsonDocument::fromJson(responseData, &parseError);
    
    if (parseError.error != QJsonParseError::NoError) {
        qDebug() << "同步网盘JSON解析错误:" << parseError.errorString();
        emit syncDisksCompleted(-2, "响应数据格式错误");
        return;
    }
    
    if (!doc.isObject()) {
        qDebug() << "同步网盘响应数据不是有效的JSON对象";
        emit syncDisksCompleted(-3, "响应数据格式错误");
        return;
    }
    
    QJsonObject response = doc.object();
    parseSyncDisksResponse(response);
}

void BackendService::parseSyncDisksResponse(const QJsonObject &response)
{
    // 解析响应字段
    int errcode = response["errcode"].toInt();
    QString errmsg = response["errmsg"].toString();
    
    qDebug() << "同步网盘结果 - 错误码:" << errcode << "错误消息:" << errmsg;
    
    if (errcode == 0) {
        // 解析网盘数据
        if (response.contains("data") && response["data"].isArray()) {
            QJsonArray dataArray = response["data"].toArray();
            qDebug() << "同步网盘 - 获取到网盘数量:" << dataArray.size();
            
            // 过滤掉null值并发送网盘数据信号
            QJsonArray validDisks;
            for (int i = 0; i < dataArray.size(); ++i) {
                if (!dataArray[i].isNull()) {
                    validDisks.append(dataArray[i]);
                    qDebug() << "同步网盘 - 网盘数据:" << dataArray[i];
                }
            }
            
            // 发送网盘数据信号，用于更新数据库
            emit syncDisksData(validDisks);
            
            // 检查并设置默认网盘
            setDefaultDisk(validDisks);
            
            // 自动同步所有网盘的文件夹
            if (!validDisks.isEmpty()) {
                qDebug() << "syncDisk执行完成，开始同步所有网盘的文件夹，网盘数量:" << validDisks.size();
                for (int i = 0; i < validDisks.size(); ++i) {
                    QJsonValue diskValue = validDisks[i];
                    if (diskValue.isObject()) {
                        QJsonObject disk = diskValue.toObject();
                        QString diskId = disk["id"].toString();
                        QString diskName = disk["name"].toString();
                        if (!diskId.isEmpty()) {
                            qDebug() << "同步网盘文件夹，网盘ID:" << diskId << "网盘名称:" << diskName;
                            syncFolders(diskId);
                        }
                    }
                }
            } else {
                qDebug() << "syncDisk执行完成，但没有网盘数据，跳过文件夹同步";
            }
            
            // 发送同步完成信号
            emit syncDisksCompleted(0, "同步网盘成功，共" + QString::number(validDisks.size()) + "个网盘");
        } else {
            qDebug() << "同步网盘 - 响应中没有data字段或data不是数组";
            emit syncDisksCompleted(-4, "响应数据格式错误：缺少data字段");
        }
    } else {
        qDebug() << "同步网盘失败:" << errmsg;
        emit syncDisksCompleted(errcode, errmsg);
    }
}

void BackendService::saveToken(const QString &checkInToken)
{
    m_checkInToken = checkInToken;
    
    // 获取用户主目录
    QString homePath = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
    if (homePath.isEmpty()) {
        qDebug() << "无法获取用户主目录，无法保存checkInToken";
        return;
    }
    
    // 构建设置文件路径
    QString settingsPath = QDir(homePath).filePath(".myapps/setting.ini");
    
    // 确保目录存在
    QDir dir;
    QString settingsDir = QFileInfo(settingsPath).absolutePath();
    if (!dir.exists(settingsDir)) {
        if (!dir.mkpath(settingsDir)) {
            qDebug() << "无法创建设置目录:" << settingsDir;
            return;
        }
    }
    
    // 保存token到设置文件
    QSettings settings(settingsPath, QSettings::IniFormat);
    settings.setValue("Auth/CheckInToken", checkInToken);
    
    qDebug() << "Token已保存到:" << settingsPath;
    qDebug() << "Token值:" << checkInToken;
}

QString BackendService::loadAccessToken()
{
    // 如果内存中已有checkInToken，直接返回
    if (!m_checkInToken.isEmpty()) {
        return m_checkInToken;
    }
    
    // 从设置文件加载checkInToken
    QString homePath = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
    if (homePath.isEmpty()) {
        qDebug() << "无法获取用户主目录，无法加载checkInToken";
        return QString();
    }
    
    QString settingsPath = QDir(homePath).filePath(".myapps/setting.ini");
    
    if (!QFile::exists(settingsPath)) {
        qDebug() << "设置文件不存在:" << settingsPath;
        return QString();
    }
    
    QSettings settings(settingsPath, QSettings::IniFormat);
    QString checkInToken = settings.value("Auth/CheckInToken", "").toString();
    
    if (!checkInToken.isEmpty()) {
        m_checkInToken = checkInToken;
        qDebug() << "从设置文件加载checkInToken成功:" << checkInToken;
    } else {
        qDebug() << "设置文件中没有找到checkInToken";
    }
    
    return checkInToken;
}

void BackendService::clearToken()
{
    m_checkInToken.clear();
    
    // 从设置文件中删除token
    QString homePath = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
    if (homePath.isEmpty()) {
        qDebug() << "无法获取用户主目录，无法清除token";
        return;
    }
    
    QString settingsPath = QDir(homePath).filePath(".myapps/setting.ini");
    
    if (QFile::exists(settingsPath)) {
        QSettings settings(settingsPath, QSettings::IniFormat);
        settings.remove("Auth/CheckInToken");
        qDebug() << "Token已从设置文件中清除";
    }
}

void BackendService::addTokenToRequest(QNetworkRequest &request)
{
    // 如果有accessToken，直接使用
    if (!m_accessToken.isEmpty()) {
        request.setRawHeader("accessToken", m_accessToken.toUtf8());
        qDebug() << "已添加accessToken到请求头:" << m_accessToken;
    } else {
        qDebug() << "没有可用的accessToken，跳过添加请求头";
    }
}

void BackendService::ensureAccessToken(const QString &domainId)
{
    // 如果已经有accessToken，不需要重新获取
    if (!m_accessToken.isEmpty()) {
        qDebug() << "已有accessToken，无需重新获取";
        return;
    }
    
    // 确保有checkInToken
    if (m_checkInToken.isEmpty()) {
        loadAccessToken();
    }
    
    // 如果有checkInToken但没有accessToken，则调用exchangeAccessToken
    if (!m_checkInToken.isEmpty() && m_accessToken.isEmpty()) {
        qDebug() << "需要获取accessToken，调用exchangeAccessToken接口";
        exchangeAccessToken(domainId);
    } else if (m_checkInToken.isEmpty()) {
        qDebug() << "没有checkInToken，无法获取accessToken";
    }
}

void BackendService::saveDomains(const QJsonArray &domains)
{
    m_domains = domains;
    
    // 获取用户主目录
    QString homePath = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
    if (homePath.isEmpty()) {
        qDebug() << "无法获取用户主目录，无法保存domains";
        return;
    }
    
    // 构建设置文件路径
    QString settingsPath = QDir(homePath).filePath(".myapps/setting.ini");
    
    // 确保目录存在
    QDir dir;
    QString settingsDir = QFileInfo(settingsPath).absolutePath();
    if (!dir.exists(settingsDir)) {
        if (!dir.mkpath(settingsDir)) {
            qDebug() << "无法创建设置目录:" << settingsDir;
            return;
        }
    }
    
    // 将domains转换为JSON字符串保存
    QJsonDocument doc(domains);
    QString domainsJson = doc.toJson(QJsonDocument::Compact);
    
    // 保存domains到设置文件
    QSettings settings(settingsPath, QSettings::IniFormat);
    settings.setValue("Auth/Domains", domainsJson);
    
    qDebug() << "Domains已保存到:" << settingsPath;
    qDebug() << "Domains数量:" << domains.size();
    qDebug() << "Domains JSON:" << domainsJson;
    
    // 在保存domains后设置默认公司
    qDebug() << "保存domains后，检查并设置默认公司";
    setDefaultCompany();
}

QJsonArray BackendService::loadDomains()
{
    // 如果内存中已有domains，直接返回
    if (!m_domains.isEmpty()) {
        return m_domains;
    }
    
    // 从设置文件加载domains
    QString homePath = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
    if (homePath.isEmpty()) {
        qDebug() << "无法获取用户主目录，无法加载domains";
        return QJsonArray();
    }
    
    QString settingsPath = QDir(homePath).filePath(".myapps/setting.ini");
    
    if (!QFile::exists(settingsPath)) {
        qDebug() << "设置文件不存在:" << settingsPath;
        return QJsonArray();
    }
    
    QSettings settings(settingsPath, QSettings::IniFormat);
    QString domainsJson = settings.value("Auth/Domains", "").toString();
    
    if (!domainsJson.isEmpty()) {
        // 解析JSON字符串
        QJsonParseError parseError;
        QJsonDocument doc = QJsonDocument::fromJson(domainsJson.toUtf8(), &parseError);
        
        if (parseError.error == QJsonParseError::NoError && doc.isArray()) {
            m_domains = doc.array();
            qDebug() << "从设置文件加载domains成功，数量:" << m_domains.size();
            qDebug() << "Domains JSON:" << domainsJson;
        } else {
            qDebug() << "解析domains JSON失败:" << parseError.errorString();
        }
    } else {
        qDebug() << "设置文件中没有找到domains";
    }
    
    return m_domains;
}

void BackendService::clearDomains()
{
    m_domains = QJsonArray();
    
    // 从设置文件中删除domains
    QString homePath = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
    if (homePath.isEmpty()) {
        qDebug() << "无法获取用户主目录，无法清除domains";
        return;
    }
    
    QString settingsPath = QDir(homePath).filePath(".myapps/setting.ini");
    
    if (QFile::exists(settingsPath)) {
        QSettings settings(settingsPath, QSettings::IniFormat);
        settings.remove("Auth/Domains");
        qDebug() << "Domains已从设置文件中清除";
    }
}

QVariantList BackendService::getDomains()
{
    QJsonArray domains = loadDomains();
    QVariantList result;
    
    for (const QJsonValue &value : domains) {
        if (value.isObject()) {
            QJsonObject domain = value.toObject();
            QVariantMap domainMap;
            domainMap["id"] = domain["id"].toString();
            domainMap["name"] = domain["name"].toString();
            domainMap["weixinCorpId"] = domain["weixinCorpId"].toString();
            domainMap["islog"] = domain["islog"].toBool();
            domainMap["logoUrl"] = domain["logoUrl"].toString();
            domainMap["status"] = domain["status"].toInt();
            result.append(domainMap);
        }
    }
    
    qDebug() << "获取domains信息，数量:" << result.size();
    return result;
}

QString BackendService::getAccessToken()
{
    qDebug() << "获取访问令牌:" << m_accessToken;
    return m_accessToken;
}

void BackendService::saveSelectedCompany(const QString &companyId, const QString &companyName)
{
    // 获取用户主目录
    QString homePath = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
    if (homePath.isEmpty()) {
        qDebug() << "无法获取用户主目录，无法保存选中的公司";
        return;
    }
    
    // 构建设置文件路径
    QString settingsPath = QDir(homePath).filePath(".myapps/setting.ini");
    
    // 确保目录存在
    QDir dir;
    QString settingsDir = QFileInfo(settingsPath).absolutePath();
    if (!dir.exists(settingsDir)) {
        if (!dir.mkpath(settingsDir)) {
            qDebug() << "无法创建设置目录:" << settingsDir;
            return;
        }
    }
    
    // 保存选中的公司ID到设置文件（只保存ID，名称从domains中获取）
    QSettings settings(settingsPath, QSettings::IniFormat);
    settings.setValue("Selection/SelectedCompanyId", companyId);
    settings.sync();
    
    qDebug() << "已保存选中的公司ID到设置文件:" << companyId;
}

QStringList BackendService::loadSelectedCompany()
{
    QStringList result;
    
    // 获取用户主目录
    QString homePath = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
    if (homePath.isEmpty()) {
        qDebug() << "无法获取用户主目录，无法加载选中的公司";
        return result;
    }
    
    // 构建设置文件路径
    QString settingsPath = QDir(homePath).filePath(".myapps/setting.ini");
    
    if (!QFile::exists(settingsPath)) {
        qDebug() << "设置文件不存在，无法加载选中的公司";
        return result;
    }
    
    // 从设置文件加载选中的公司
    QSettings settings(settingsPath, QSettings::IniFormat);
    QString companyId = settings.value("Company/SelectedId", "").toString();
    QString companyName = settings.value("Company/SelectedName", "").toString();
    
    if (!companyId.isEmpty() && !companyName.isEmpty()) {
        result << companyId << companyName;
        qDebug() << "已加载选中的公司:" << companyName << "ID:" << companyId;
    } else {
        qDebug() << "没有找到保存的选中公司信息";
    }
    
    return result;
}

void BackendService::syncFolders(const QString &diskId)
{
    // 检查是否有accessToken，如果没有则先获取
    if (m_accessToken.isEmpty()) {
        // 获取当前选中的公司ID
        QString companyId = loadSelectedCompanyId();
        if (!companyId.isEmpty()) {
            qDebug() << "没有accessToken，先获取accessToken，公司ID:" << companyId;
            m_pendingSyncDiskId = diskId; // 保存待同步的网盘ID
            ensureAccessToken(companyId);
            // 注意：这里不能立即发送请求，因为ensureAccessToken是异步的
            // 需要在exchangeAccessTokenCompleted信号中重新调用syncFolders
            return;
        } else {
            qDebug() << "没有选中的公司ID，无法获取accessToken";
            emit syncFoldersCompleted(-1, "没有选中的公司ID，无法获取accessToken");
            return;
        }
    }
    
    // 构建请求URL
    QString url = m_baseUrl + QString("/kms/api/kms/sync/disks/%1/folders").arg(diskId);
    
    qDebug() << "发送同步文件夹请求到:" << url;
    
    // 创建网络请求
    QNetworkRequest request;
    request.setUrl(QUrl(url));
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
    
    // 添加token到请求头
    addTokenToRequest(request);
    
    // 发送GET请求
    QNetworkReply *reply = m_networkManager->get(request);
    qDebug() << "发送同步文件夹请求，reply对象:" << reply;
    
    // 设置用户数据，用于识别请求类型
    reply->setProperty("requestType", "syncFolders");
}

void BackendService::handleSyncFoldersResponse(QNetworkReply *reply)
{
    // 检查网络错误
    if (reply->error() != QNetworkReply::NoError) {
        qDebug() << "同步文件夹网络请求错误:" << reply->errorString();
        emit syncFoldersCompleted(-1, "网络请求失败: " + reply->errorString());
        return;
    }
    
    // 读取响应数据
    QByteArray responseData = reply->readAll();
    qDebug() << "同步文件夹响应数据包:" << responseData;
    
    // 解析JSON响应
    QJsonParseError parseError;
    QJsonDocument doc = QJsonDocument::fromJson(responseData, &parseError);
    
    if (parseError.error != QJsonParseError::NoError) {
        qDebug() << "同步文件夹JSON解析错误:" << parseError.errorString();
        emit syncFoldersCompleted(-1, "JSON解析失败: " + parseError.errorString());
        return;
    }
    
    if (!doc.isObject()) {
        qDebug() << "同步文件夹响应不是有效的JSON对象";
        emit syncFoldersCompleted(-1, "响应格式错误");
        return;
    }
    
    QJsonObject response = doc.object();
    parseSyncFoldersResponse(response);
}

void BackendService::parseSyncFoldersResponse(const QJsonObject &response)
{
    int errcode = response["errcode"].toInt();
    QString errmsg = response["errmsg"].toString();
    
    if (errcode == 0) {
        qDebug() << "同步文件夹成功:" << errmsg;
        
        // 解析data数组
        if (response.contains("data") && response["data"].isArray()) {
            QJsonArray foldersArray = response["data"].toArray();
            
            // 过滤掉null值
            QJsonArray validFolders;
            for (const QJsonValue &value : foldersArray) {
                if (!value.isNull()) {
                    validFolders.append(value);
                }
            }
            
            qDebug() << "同步文件夹数据，有效文件夹数量:" << validFolders.size();
            emit syncFoldersData(validFolders);
        } else {
            qDebug() << "同步文件夹响应中没有data数组或data不是数组";
        }
        
        emit syncFoldersCompleted(errcode, errmsg);
    } else {
        qDebug() << "同步文件夹失败:" << errmsg;
        emit syncFoldersCompleted(errcode, errmsg);
    }
}

void BackendService::saveSelectedCompanyId(const QString &companyId)
{
    // 获取用户主目录
    QString homePath = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
    if (homePath.isEmpty()) {
        qDebug() << "无法获取用户主目录，无法保存选中的公司ID";
        return;
    }
    
    // 构建设置文件路径
    QString settingsPath = QDir(homePath).filePath(".myapps/setting.ini");
    
    QSettings settings(settingsPath, QSettings::IniFormat);
    settings.setValue("Selection/SelectedCompanyId", companyId);
    qDebug() << "已保存选中的公司ID:" << companyId;
}

QString BackendService::loadSelectedCompanyId()
{
    // 获取用户主目录
    QString homePath = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
    if (homePath.isEmpty()) {
        qDebug() << "无法获取用户主目录，无法加载选中的公司ID";
        return "";
    }
    
    // 构建设置文件路径
    QString settingsPath = QDir(homePath).filePath(".myapps/setting.ini");
    
    QSettings settings(settingsPath, QSettings::IniFormat);
    QString companyId = settings.value("Selection/SelectedCompanyId", "").toString();
    qDebug() << "已加载选中的公司ID:" << companyId;
    return companyId;
}

void BackendService::saveSelectedDiskId(const QString &diskId)
{
    // 获取用户主目录
    QString homePath = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
    QString settingsPath = QDir(homePath).filePath(".myapps/setting.ini");
    QSettings settings(settingsPath, QSettings::IniFormat);
    settings.setValue("Selection/SelectedDiskId", diskId);
    qDebug() << "已保存选中的网盘ID:" << diskId;
}

QString BackendService::loadSelectedDiskId()
{
    QString homePath = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
    QString settingsPath = QDir(homePath).filePath(".myapps/setting.ini");
    QSettings settings(settingsPath, QSettings::IniFormat);
    QString diskId = settings.value("Selection/SelectedDiskId", "").toString();
    qDebug() << "已加载选中的网盘ID:" << diskId;
    return diskId;
}

void BackendService::setDefaultCompany()
{
    // 检查是否有保存的公司ID
    QString savedCompanyId = loadSelectedCompanyId();
    bool needSetDefault = false;
    
    if (savedCompanyId.isEmpty()) {
        qDebug() << "没有保存的公司ID，需要设置默认公司";
        needSetDefault = true;
    } else {
        // 检查保存的公司ID是否在domains中
        bool found = false;
        
        for (const QJsonValue &value : m_domains) {
            if (value.isObject()) {
                QJsonObject domain = value.toObject();
                QString domainId = domain["id"].toString();
                if (domainId == savedCompanyId) {
                    found = true;
                    qDebug() << "保存的公司ID在domains中找到:" << savedCompanyId;
                    break;
                }
            }
        }
        
        if (!found) {
            qDebug() << "保存的公司ID不在domains中，需要设置默认公司";
            needSetDefault = true;
        }
    }
    
    if (needSetDefault && !m_domains.isEmpty()) {
        // 设置domains中第一个为公司为默认
        QJsonValue firstDomain = m_domains.first();
        if (firstDomain.isObject()) {
            QJsonObject domain = firstDomain.toObject();
            QString defaultCompanyId = domain["id"].toString();
            QString defaultCompanyName = domain["name"].toString();
            
            // 保存为默认公司
            saveSelectedCompanyId(defaultCompanyId);
            
            qDebug() << "已设置默认公司:" << defaultCompanyName << "ID:" << defaultCompanyId;
        }
    }
}

void BackendService::setDefaultDisk(const QJsonArray &disksData)
{
    // 检查是否有保存的网盘ID
    QString savedDiskId = loadSelectedDiskId();
    
    if (savedDiskId.isEmpty()) {
        qDebug() << "没有保存的网盘ID，需要设置默认网盘";
    } else {
        qDebug() << "已有保存的网盘ID:" << savedDiskId << "，但syncDisks成功后需要重新设置默认网盘";
    }
    
    if (!disksData.isEmpty()) {
        // 设置disks中第一个为默认网盘
        QJsonValue firstDisk = disksData.first();
        if (firstDisk.isObject()) {
            QJsonObject disk = firstDisk.toObject();
            QString defaultDiskId = disk["id"].toString();
            QString defaultDiskName = disk["name"].toString();
            
            // 保存为默认网盘
            saveSelectedDiskId(defaultDiskId);
            
            qDebug() << "syncDisks成功后已设置默认网盘:" << defaultDiskName << "ID:" << defaultDiskId;
        }
    } else {
        qDebug() << "网盘数据为空，无法设置默认网盘";
    }
}

void BackendService::exchangeAccessToken(const QString &domainId)
{
    // 构建请求URL
    QString url = m_baseUrl + "/signon/api/login/exchangeAccessToken";
    
    qDebug() << "发送获取AccessToken请求到:" << url;
    qDebug() << "domainId:" << domainId;
    
    // 创建网络请求
    QNetworkRequest request;
    request.setUrl(QUrl(url));
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
    
    // 构建请求体
    QJsonObject requestBody;
    requestBody["checkInToken"] = m_checkInToken;
    requestBody["domainId"] = domainId;
    
    QJsonDocument doc(requestBody);
    QByteArray data = doc.toJson();
    
    qDebug() << "请求体:" << data;
    
    // 发送POST请求
    QNetworkReply *reply = m_networkManager->post(request, data);
    qDebug() << "发送获取AccessToken请求，reply对象:" << reply;
    
    // 设置用户数据，用于识别请求类型
    reply->setProperty("requestType", "exchangeAccessToken");
}

void BackendService::handleExchangeAccessTokenResponse(QNetworkReply *reply)
{
    // 检查网络错误
    if (reply->error() != QNetworkReply::NoError) {
        qDebug() << "获取AccessToken网络请求错误:" << reply->errorString();
        emit exchangeAccessTokenCompleted(-1, "网络请求失败: " + reply->errorString(), "");
        return;
    }
    
    // 读取响应数据
    QByteArray responseData = reply->readAll();
    qDebug() << "获取AccessToken响应数据包:" << responseData;
    
    // 解析JSON响应
    QJsonParseError parseError;
    QJsonDocument doc = QJsonDocument::fromJson(responseData, &parseError);
    
    if (parseError.error != QJsonParseError::NoError) {
        qDebug() << "获取AccessToken JSON解析错误:" << parseError.errorString();
        emit exchangeAccessTokenCompleted(-1, "JSON解析失败: " + parseError.errorString(), "");
        return;
    }
    
    if (!doc.isObject()) {
        qDebug() << "获取AccessToken响应不是有效的JSON对象";
        emit exchangeAccessTokenCompleted(-1, "响应格式错误", "");
        return;
    }
    
    QJsonObject response = doc.object();
    parseExchangeAccessTokenResponse(response);
}

void BackendService::parseExchangeAccessTokenResponse(const QJsonObject &response)
{
    int resultCode = response["resultCode"].toInt();
    QString msg = response["msg"].toString();
    
    if (resultCode == 0) {
        // 成功获取AccessToken
        QString accessToken = response["accessToken"].toString();
        
        if (!accessToken.isEmpty()) {
            m_accessToken = accessToken;
            qDebug() << "成功获取AccessToken:" << accessToken;
            
            // 执行待处理的操作
            if (m_pendingSyncDiskId.isEmpty()) {
                // 同步网盘
                qDebug() << "AccessToken获取成功，重新执行同步网盘操作";
                syncDisks();
            } else if (m_pendingSyncFolderId.isEmpty()) {
                // 同步文件夹
                qDebug() << "AccessToken获取成功，重新执行同步文件夹操作，网盘ID:" << m_pendingSyncDiskId;
                QString diskId = m_pendingSyncDiskId;
                m_pendingSyncDiskId.clear(); // 清除待处理状态
                syncFolders(diskId);
            } else if (m_pendingCommitSourceFileId.isEmpty()) {
                // 同步文件
                qDebug() << "AccessToken获取成功，重新执行同步文件操作，网盘ID:" << m_pendingSyncDiskId << "文件夹ID:" << m_pendingSyncFolderId;
                QString diskId = m_pendingSyncDiskId;
                QString folderId = m_pendingSyncFolderId;
                m_pendingSyncDiskId.clear(); // 清除待处理状态
                m_pendingSyncFolderId.clear(); // 清除待处理状态
                syncFiles(diskId, folderId);
            } else {
                // 提交文件
                qDebug() << "AccessToken获取成功，重新执行文件提交操作，网盘ID:" << m_pendingSyncDiskId << "文件夹ID:" << m_pendingSyncFolderId << "源文件ID:" << m_pendingCommitSourceFileId;
                QString diskId = m_pendingSyncDiskId;
                QString folderId = m_pendingSyncFolderId;
                QString sourceFileId = m_pendingCommitSourceFileId;
                m_pendingSyncDiskId.clear(); // 清除待处理状态
                m_pendingSyncFolderId.clear(); // 清除待处理状态
                m_pendingCommitSourceFileId.clear(); // 清除待处理状态
                commitFile(diskId, folderId, sourceFileId);
            }
            
            emit exchangeAccessTokenCompleted(resultCode, msg, accessToken);
        } else {
            qDebug() << "获取AccessToken响应中没有accessToken字段";
            emit exchangeAccessTokenCompleted(-1, "响应中没有accessToken字段", "");
        }
    } else {
        qDebug() << "获取AccessToken失败:" << msg;
        emit exchangeAccessTokenCompleted(resultCode, msg, "");
    }
}

void BackendService::syncFiles(const QString &diskId, const QString &folderId)
{
    // 检查是否有accessToken，如果没有则先获取
    if (m_accessToken.isEmpty()) {
        // 获取当前选中的公司ID
        QString companyId = loadSelectedCompanyId();
        if (!companyId.isEmpty()) {
            qDebug() << "没有accessToken，先获取accessToken，公司ID:" << companyId;
            m_pendingSyncDiskId = diskId; // 保存待同步的网盘ID
            m_pendingSyncFolderId = folderId; // 保存待同步的文件夹ID
            ensureAccessToken(companyId);
            // 注意：这里不能立即发送请求，因为ensureAccessToken是异步的
            // 需要在exchangeAccessTokenCompleted信号中重新调用syncFiles
            return;
        } else {
            qDebug() << "没有选中的公司ID，无法获取accessToken";
            emit syncFilesCompleted(-1, "没有选中的公司ID，无法获取accessToken");
            return;
        }
    }
    
    // 构建请求URL
    QString url = m_baseUrl + QString("/kms/api/kms/sync/disks/%1/folders/%2/files").arg(diskId, folderId);
    
    qDebug() << "发送同步文件请求到:" << url;
    qDebug() << "网盘ID:" << diskId << "文件夹ID:" << folderId;
    
    // 创建网络请求
    QNetworkRequest request;
    request.setUrl(QUrl(url));
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
    
    // 添加token到请求头
    addTokenToRequest(request);
    
    // 发送GET请求
    QNetworkReply *reply = m_networkManager->get(request);
    qDebug() << "发送同步文件请求，reply对象:" << reply;
    
    // 设置用户数据，用于识别请求类型
    reply->setProperty("requestType", "syncFiles");
}

void BackendService::handleSyncFilesResponse(QNetworkReply *reply)
{
    // 检查网络错误
    if (reply->error() != QNetworkReply::NoError) {
        qDebug() << "同步文件网络请求错误:" << reply->errorString();
        emit syncFilesCompleted(-1, "网络请求失败: " + reply->errorString());
        return;
    }
    
    // 读取响应数据
    QByteArray responseData = reply->readAll();
    qDebug() << "同步文件响应数据包:" << responseData;
    
    // 解析JSON响应
    QJsonParseError parseError;
    QJsonDocument doc = QJsonDocument::fromJson(responseData, &parseError);
    
    if (parseError.error != QJsonParseError::NoError) {
        qDebug() << "同步文件JSON解析错误:" << parseError.errorString();
        emit syncFilesCompleted(-1, "JSON解析失败: " + parseError.errorString());
        return;
    }
    
    if (!doc.isObject()) {
        qDebug() << "同步文件响应不是有效的JSON对象";
        emit syncFilesCompleted(-1, "响应格式错误");
        return;
    }
    
    QJsonObject response = doc.object();
    parseSyncFilesResponse(response);
}

void BackendService::parseSyncFilesResponse(const QJsonObject &response)
{
    int errcode = response["errcode"].toInt();
    QString errmsg = response["errmsg"].toString();
    
    qDebug() << "同步文件结果 - 错误码:" << errcode << "错误消息:" << errmsg;
    
    if (errcode == 0) {
        // 解析文件数据
        if (response.contains("data") && response["data"].isArray()) {
            QJsonArray dataArray = response["data"].toArray();
            qDebug() << "同步文件 - 获取到文件数量:" << dataArray.size();
            
            // 过滤掉null值并发送文件数据信号
            QJsonArray validFiles;
            for (int i = 0; i < dataArray.size(); ++i) {
                if (!dataArray[i].isNull()) {
                    validFiles.append(dataArray[i]);
                    qDebug() << "同步文件 - 文件数据:" << dataArray[i];
                }
            }
            
            // 发送文件数据信号，用于更新数据库
            emit syncFilesData(validFiles);
            
            // 发送同步完成信号
            emit syncFilesCompleted(0, "同步文件成功，共" + QString::number(validFiles.size()) + "个文件");
        } else if (!response.contains("data")) {
            // 当没有data字段时，表示没有文件需要同步，这是正常情况
            qDebug() << "同步文件 - 没有data字段，表示没有文件需要同步";
            emit syncFilesCompleted(0, "同步文件成功，没有文件需要同步");
        } else {
            qDebug() << "同步文件 - data字段不是数组";
            emit syncFilesCompleted(-4, "响应数据格式错误：data字段不是数组");
        }
    } else {
        qDebug() << "同步文件失败:" << errmsg;
        emit syncFilesCompleted(errcode, errmsg);
    }
}

void BackendService::getKmsFileByFileId(const QString &fileId)
{
    if (fileId.isEmpty()) {
        qDebug() << "文件ID为空，无法获取文件信息";
        emit getKmsFileByFileIdCompleted(-1, "文件ID为空", QVariantMap());
        return;
    }
    
    // 检查是否有accessToken，如果没有则先获取
    if (m_accessToken.isEmpty()) {
        // 获取当前选中的公司ID
        QString companyId = loadSelectedCompanyId();
        if (!companyId.isEmpty()) {
            qDebug() << "没有accessToken，先获取accessToken，公司ID:" << companyId;
            ensureAccessToken(companyId);
            // 注意：这里不能立即发送请求，因为ensureAccessToken是异步的
            // 需要在exchangeAccessTokenCompleted信号中重新调用getKmsFileByFileId
            return;
        } else {
            qDebug() << "没有选中的公司ID，无法获取accessToken";
            emit getKmsFileByFileIdCompleted(-1, "没有选中的公司ID，无法获取accessToken", QVariantMap());
            return;
        }
    }
    
    // 构建请求URL
    QString url = m_baseUrl + QString("/kms/api/kms/sync/files/%1").arg(fileId);
    
    qDebug() << "发送获取KmsFile请求到:" << url;
    qDebug() << "文件ID:" << fileId;
    
    // 创建网络请求
    QNetworkRequest request = createRequest(url, "GET");
    
    // 添加token到请求头
    addTokenToRequest(request);
    
    // 设置请求属性，用于识别请求类型
    request.setAttribute(QNetworkRequest::User, "getKmsFileByFileId");
    
    // 发送GET请求
    QNetworkReply *reply = m_networkManager->get(request);
    qDebug() << "发送获取KmsFile请求，reply对象:" << reply;
    
    if (reply) {
        // 设置请求类型属性
        reply->setProperty("requestType", "getKmsFileByFileId");
        // 保存文件ID，用于响应处理
        reply->setProperty("fileId", fileId);
    }
}

void BackendService::handleGetKmsFileResponse(QNetworkReply *reply)
{
    // 检查网络错误
    if (reply->error() != QNetworkReply::NoError) {
        qDebug() << "获取KmsFile网络请求错误:" << reply->errorString();
        emit getKmsFileByFileIdCompleted(-1, "网络请求失败: " + reply->errorString(), QVariantMap());
        return;
    }
    
    // 读取响应数据
    QByteArray responseData = reply->readAll();
    qDebug() << "获取KmsFile响应数据包:" << responseData;
    
    // 解析JSON响应
    QJsonParseError parseError;
    QJsonDocument doc = QJsonDocument::fromJson(responseData, &parseError);
    
    if (parseError.error != QJsonParseError::NoError) {
        qDebug() << "获取KmsFile JSON解析错误:" << parseError.errorString();
        emit getKmsFileByFileIdCompleted(-1, "JSON解析失败: " + parseError.errorString(), QVariantMap());
        return;
    }
    
    if (!doc.isObject()) {
        qDebug() << "获取KmsFile响应不是有效的JSON对象";
        emit getKmsFileByFileIdCompleted(-1, "响应格式错误", QVariantMap());
        return;
    }
    
    QJsonObject response = doc.object();
    parseGetKmsFileResponse(response);
}

void BackendService::parseGetKmsFileResponse(const QJsonObject &response)
{
    int errcode = response["errcode"].toInt();
    QString errmsg = response["errmsg"].toString();
    
    qDebug() << "获取KmsFile结果 - 错误码:" << errcode << "错误消息:" << errmsg;
    
    if (errcode == 0) {
        // 解析文件数据
        if (response.contains("data") && response["data"].isObject()) {
            QJsonObject fileData = response["data"].toObject();
            qDebug() << "获取KmsFile - 文件数据:" << fileData;
            
            // 将QJsonObject转换为QVariantMap以便通过信号传递
            QVariantMap fileMap;
            fileMap["id"] = fileData["id"].toString();
            fileMap["name"] = fileData["name"].toString();
            fileMap["creatorId"] = fileData["creatorId"].toString();
            fileMap["creator"] = fileData["creator"].toString();
            fileMap["createDate"] = fileData["createDate"].toString();
            fileMap["lastModifyDate"] = fileData["lastModifyDate"].toString();
            fileMap["diskId"] = fileData["diskId"].toString();
            fileMap["domainId"] = fileData["domainId"].isNull() ? QVariant() : fileData["domainId"].toString();
            fileMap["folderId"] = fileData["folderId"].toString();
            fileMap["folder"] = fileData["folder"].toBool();
            fileMap["size"] = fileData["size"].toVariant();
            fileMap["path"] = fileData["path"].toString();
            fileMap["removeOperator"] = fileData["removeOperator"].isNull() ? QVariant() : fileData["removeOperator"].toString();
            fileMap["version"] = fileData["version"].toInt();
            fileMap["orderNo"] = fileData["orderNo"].toInt();
            fileMap["type"] = fileData["type"].toInt();
            fileMap["maxVersion"] = fileData["maxVersion"].toInt();
            fileMap["head"] = fileData["head"].toBool();
            fileMap["recycleDelete"] = fileData["recycleDelete"].toBool();
            fileMap["delete"] = fileData["delete"].toBool();
            
            // 发送完成信号
            emit getKmsFileByFileIdCompleted(0, "获取KmsFile成功", fileMap);
        } else {
            qDebug() << "获取KmsFile - data字段不是对象或不存在";
            emit getKmsFileByFileIdCompleted(-4, "响应数据格式错误：data字段不是对象", QVariantMap());
        }
    } else {
        qDebug() << "获取KmsFile失败:" << errmsg;
        emit getKmsFileByFileIdCompleted(errcode, errmsg, QVariantMap());
    }
}

void BackendService::selectAndUploadFile(const QString &folderId)
{
    if (!m_databaseManager) {
        qDebug() << "数据库管理器未设置，无法上传文件";
        return;
    }
    
    // 打开文件选择对话框
    QString fileName = QFileDialog::getOpenFileName(
        nullptr,
        "选择要上传的文件",
        QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation),
        "所有文件 (*.*)"
    );
    
    if (fileName.isEmpty()) {
        qDebug() << "用户取消了文件选择";
        return;
    }
    
    qDebug() << "选择文件:" << fileName;
    
    // 查询文件夹信息以获取 diskId
    KmsFolder folder = m_databaseManager->queryFolderById(folderId);
    if (folder.id.isEmpty()) {
        qDebug() << "未找到文件夹，文件夹ID:" << folderId;
        return;
    }
    
    QString diskId = folder.diskId;
    if (diskId.isEmpty()) {
        qDebug() << "文件夹没有关联的网盘ID";
        return;
    }
    
    qDebug() << "文件夹信息 - 名称:" << folder.name << "网盘ID:" << diskId;
    
    // 获取文件信息
    QFileInfo fileInfo(fileName);
    if (!fileInfo.exists()) {
        qDebug() << "文件不存在:" << fileName;
        return;
    }
    
    QString sourceFileName = fileInfo.fileName();
    qint64 fileSize = fileInfo.size();
    
    // 获取工作目录
    QString workBaseDir = getUserWorkBaseDir();
    if (workBaseDir.isEmpty()) {
        qDebug() << "用户工作目录未设置";
        return;
    }
    
    // 构建目标文件路径（相对于工作目录）
    // 使用文件夹路径作为基础路径，规范化路径分隔符
    QString normalizedFolderPath = folder.path;
    normalizedFolderPath.replace("\\", "/");
    if (normalizedFolderPath.startsWith("/")) {
        normalizedFolderPath = normalizedFolderPath.mid(1); // 移除开头的斜杠
    }
    
    QString relativePath = normalizedFolderPath.isEmpty() ? sourceFileName : (normalizedFolderPath + "/" + sourceFileName);
    QString targetDir = normalizedFolderPath.isEmpty() ? workBaseDir : (workBaseDir + "/" + normalizedFolderPath);
    QString targetFilePath = workBaseDir + "/" + relativePath;
    
    // 确保目标目录存在
    QDir targetDirObj(targetDir);
    if (!targetDirObj.exists()) {
        if (!targetDirObj.mkpath(".")) {
            qDebug() << "无法创建目标目录:" << targetDir;
            return;
        }
    }
    
    // 复制文件到工作目录
    QFile sourceFile(fileName);
    if (!sourceFile.copy(targetFilePath)) {
        qDebug() << "复制文件失败:" << sourceFile.errorString();
        return;
    }
    
    qDebug() << "文件已复制到:" << targetFilePath;
    
    // 计算文件校验和（SHA-1）
    QFile targetFile(targetFilePath);
    if (!targetFile.open(QIODevice::ReadOnly)) {
        qDebug() << "无法打开目标文件计算校验和";
        return;
    }
    
    QCryptographicHash hash(QCryptographicHash::Sha1);
    if (!hash.addData(&targetFile)) {
        qDebug() << "计算文件校验和失败";
        targetFile.close();
        return;
    }
    targetFile.close();
    
    QString checksum = hash.result().toHex();
    
    // 生成临时文件ID（使用UUID）
    QString sourceFileId = QUuid::createUuid().toString(QUuid::WithoutBraces);
    
    // 创建 KmsFile 对象
    KmsFile kmsFile;
    kmsFile.id = sourceFileId;
    kmsFile.name = sourceFileName;
    kmsFile.diskId = diskId;
    kmsFile.folderId = folderId;
    kmsFile.creator = m_currentUsername;
    kmsFile.creatorId = m_currentUsername;
    kmsFile.type = "file";
    kmsFile.createDate = QDateTime::currentDateTime().toString(Qt::ISODate);
    kmsFile.lastModifyDate = QDateTime::currentDateTime().toString(Qt::ISODate);
    kmsFile.originType = 0;
    kmsFile.originId = sourceFileId;
    kmsFile.size = fileSize;
    kmsFile.status = 0; // 标记为未同步
    kmsFile.checksum = checksum;
    kmsFile.localFileSize = fileSize;
    kmsFile.localFileChecksum = checksum;
    kmsFile.localFilePath = relativePath;
    
    // 插入数据库
    if (!m_databaseManager->insertFile(kmsFile)) {
        qDebug() << "插入文件记录到数据库失败";
        // 删除已复制的文件
        QFile::remove(targetFilePath);
        return;
    }
    
    qDebug() << "文件记录已插入数据库，文件ID:" << sourceFileId;
    
    // 调用 commitFile 上传文件
    commitFile(diskId, folderId, sourceFileId);
}

void BackendService::commitFile(const QString &diskId, const QString &folderId, const QString &sourceFileId)
{
    // 检查是否有accessToken，如果没有则先获取
    if (m_accessToken.isEmpty()) {
        // 获取当前选中的公司ID
        QString companyId = loadSelectedCompanyId();
        if (!companyId.isEmpty()) {
            qDebug() << "没有accessToken，先获取accessToken，公司ID:" << companyId;
            m_pendingSyncDiskId = diskId;
            m_pendingSyncFolderId = folderId;
            m_pendingCommitSourceFileId = sourceFileId;
            ensureAccessToken(companyId);
            return;
        } else {
            qDebug() << "没有选中的公司ID，无法获取accessToken";
            emit commitFileCompleted(-1, "没有选中的公司ID，无法获取accessToken");
            return;
        }
    }
    
    // 构建提交文件的URL
    QString commitUrl = m_baseUrl + "/kms/api/kms/sync/commitFile";
    commitUrl += "?diskId=" + diskId;
    commitUrl += "&folderId=" + folderId;
    commitUrl += "&sourceFileId=" + sourceFileId;
    
    qDebug() << "开始提交文件，URL:" << commitUrl;
    
    // 保存当前提交的文件ID
    m_currentCommitSourceFileId = sourceFileId;
    
    // 创建网络请求
    QNetworkRequest request;
    request.setUrl(QUrl(commitUrl));
    
    // 添加token到请求头
    addTokenToRequest(request);
    
    // 创建多部分数据
    QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
    
    // 添加文件数据到multipart
    // 根据sourceFileId获取文件信息
    if (!m_databaseManager) {
        qDebug() << "数据库管理器未设置";
        emit commitFileCompleted(-1, "数据库管理器未设置");
        return;
    }
    
    KmsFile kmsFile = m_databaseManager->queryFileById(sourceFileId);
    if (kmsFile.id.isEmpty()) {
        qDebug() << "未找到文件记录，文件ID:" << sourceFileId;
        emit commitFileCompleted(-1, "未找到文件记录");
        return;
    }
    
    qDebug() << "找到文件记录，文件名:" << kmsFile.name << "本地路径:" << kmsFile.localFilePath;
    
    // 构建完整的本地文件路径
    QString workBase = getUserWorkBaseDir();
    QString localFilePath;
    
    // 优先使用 localFilePath 字段（相对于工作目录的路径）
    if (!kmsFile.localFilePath.isEmpty()) {
        localFilePath = QDir::cleanPath(workBase + "/" + kmsFile.localFilePath);
        qDebug() << "使用 localFilePath 字段构建本地路径";
    } else {
        // 如果 localFilePath 为空，回退到根据文件夹路径和文件名构建
        // 从数据库获取文件夹路径
        QString folderPath = "";
        if (!kmsFile.folderId.isEmpty() && m_databaseManager) {
            // 通过查询文件夹路径来获取（使用PATH字段查询）
            // 注意：这里使用查询所有文件夹然后过滤，因为没有直接的queryFolderById方法
            // 未来可以考虑添加queryFolderById方法以提高效率
            QList<KmsFolder> allFolders = m_databaseManager->queryAllFolders();
            for (const auto &folder : allFolders) {
                if (folder.id == kmsFile.folderId) {
                    folderPath = folder.path;
                    break;
                }
            }
        }
        
        // 构建路径
        if (!folderPath.isEmpty()) {
            // 清理路径：移除开头的斜杠
            QString cleanFolderPath = folderPath;
            if (cleanFolderPath.startsWith('/')) {
                cleanFolderPath.remove(0, 1);
            }
            localFilePath = QDir::cleanPath(workBase + "/" + cleanFolderPath + "/" + kmsFile.name);
        } else {
            // 如果没有文件夹路径，只使用文件名
            localFilePath = QDir::cleanPath(workBase + "/" + kmsFile.name);
        }
        qDebug() << "回退到根据文件夹路径和文件名构建本地路径";
    }
    
    qDebug() << "本地文件路径:" << localFilePath;
    
    // 检查文件是否存在
    QFile localFile(localFilePath);
    if (!localFile.exists()) {
        qDebug() << "本地文件不存在:" << localFilePath;
        emit commitFileCompleted(-1, "本地文件不存在");
        return;
    }
    
    // 读取文件内容
    if (!localFile.open(QIODevice::ReadOnly)) {
        qDebug() << "无法打开本地文件:" << localFile.errorString();
        emit commitFileCompleted(-1, "无法打开本地文件");
        return;
    }
    
    QByteArray fileContent = localFile.readAll();
    localFile.close();
    
    qDebug() << "文件内容大小:" << fileContent.size() << "字节";
    
    // 创建文件部分
    QHttpPart filePart;
    filePart.setHeader(QNetworkRequest::ContentDispositionHeader, 
                      QVariant("form-data; name=\"files\"; filename=\"" + kmsFile.name + "\""));
    filePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/octet-stream"));
    filePart.setBody(fileContent);
    
    multiPart->append(filePart);
    
    // 发送POST请求
    QNetworkReply *reply = m_networkManager->post(request, multiPart);
    multiPart->setParent(reply); // 确保在reply删除时也删除multiPart
    
    // 让QNetworkAccessManager自动设置正确的Content-Type头
    // 包括boundary参数
    
    // 设置请求类型标识
    reply->setProperty("requestType", "commitFile");
    
    qDebug() << "文件提交请求已发送";
}

void BackendService::downloadFile(const QString &url, const QString &fileName, const QString &fileId)
{
    // 检查是否有accessToken，如果没有则先获取
    if (m_accessToken.isEmpty()) {
        // 获取当前选中的公司ID
        QString companyId = loadSelectedCompanyId();
        if (!companyId.isEmpty()) {
            qDebug() << "没有accessToken，先获取accessToken，公司ID:" << companyId;
            // 注意：这里需要保存下载参数，在获取accessToken后重新调用
            // 由于下载是文件操作，这里简化处理，直接提示需要先登录
            emit downloadFileCompleted(-1, "需要先登录获取访问令牌", "");
            return;
        } else {
            qDebug() << "没有选中的公司ID，无法获取accessToken";
            emit downloadFileCompleted(-1, "没有选中的公司ID，无法获取accessToken", "");
            return;
        }
    }
    
    // 验证文件ID
    if (fileId.isEmpty()) {
        qDebug() << "文件ID为空，无法构建下载URL";
        emit downloadFileCompleted(-1, "文件ID为空，无法下载文件", "");
        return;
    }
    
    // 构建完整的下载URL
    QString downloadUrl = m_baseUrl + "/kms/api/kms/download/" + fileId;
    
    qDebug() << "开始下载文件，URL:" << downloadUrl << "文件ID:" << fileId;
    
    // 创建网络请求
    QNetworkRequest request;
    request.setUrl(QUrl(downloadUrl));
    
    // 添加token到请求头
    addTokenToRequest(request);
    
    // 发送GET请求
    QNetworkReply *reply = m_networkManager->get(request);
    qDebug() << "发送下载文件请求，reply对象:" << reply;
    
    // 设置用户数据，用于识别请求类型
    reply->setProperty("requestType", "downloadFile");
    
    // 保存相对URL（用于构建本地保存目录结构）
    reply->setProperty("fileRelativeUrl", url);

    // 如果提供了文件名，保存到reply属性中
    if (!fileName.isEmpty()) {
        reply->setProperty("fileName", fileName);
    }
    
    // 如果提供了文件ID，保存到reply属性中（用于从数据库获取文件夹路径）
    if (!fileId.isEmpty()) {
        reply->setProperty("fileId", fileId);
    }
    
    // 连接下载进度信号
    connect(reply, &QNetworkReply::downloadProgress, this, [this](qint64 bytesReceived, qint64 bytesTotal) {
        emit downloadProgress(bytesReceived, bytesTotal);
    });
}

void BackendService::rollbackFile(const QString &fileId)
{
    // 检查是否有accessToken，如果没有则先获取
    if (m_accessToken.isEmpty()) {
        // 获取当前选中的公司ID
        QString companyId = loadSelectedCompanyId();
        if (!companyId.isEmpty()) {
            qDebug() << "没有accessToken，先获取accessToken，公司ID:" << companyId;
            // 注意：这里需要保存回撤参数，在获取accessToken后重新调用
            // 由于回撤是文件操作，这里简化处理，直接提示需要先登录
            emit rollbackFileCompleted(-1, "需要先登录获取访问令牌");
            return;
        } else {
            qDebug() << "没有选中的公司ID，无法获取accessToken";
            emit rollbackFileCompleted(-1, "没有选中的公司ID，无法获取accessToken");
            return;
        }
    }
    
    // 构建获取文件信息的URL
    QString fileInfoUrl = m_baseUrl + "/kms/api/kms/sync/files/" + fileId;
    
    qDebug() << "开始回撤文件，获取文件信息，URL:" << fileInfoUrl;
    qDebug() << "文件ID:" << fileId;
    
    // 创建网络请求
    QNetworkRequest request;
    request.setUrl(QUrl(fileInfoUrl));
    
    // 添加token到请求头
    addTokenToRequest(request);
    
    // 发送GET请求
    QNetworkReply *reply = m_networkManager->get(request);
    qDebug() << "发送回撤文件请求，reply对象:" << reply;
    
    // 设置用户数据，用于识别请求类型
    reply->setProperty("requestType", "rollbackFile");
    
    // 保存文件ID到reply属性中
    reply->setProperty("fileId", fileId);
}

void BackendService::handleDownloadFileResponse(QNetworkReply *reply)
{
    if (!reply) {
        qDebug() << "下载文件响应为空";
        emit downloadFileCompleted(-1, "下载响应为空", "");
        return;
    }
    
    qDebug() << "处理下载文件响应，错误:" << reply->error();
    
    if (reply->error() == QNetworkReply::NoError) {
        // 下载成功，保存文件
        QByteArray data = reply->readAll();
        qDebug() << "下载文件成功，数据大小:" << data.size() << "字节";

        // 构建用户工作目录: Home/.myapps/{username}/work
        const QString homeDir = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
        QString workBase = QDir::cleanPath(homeDir + "/.myapps/" + m_currentUsername + "/work");
        QString tempBase = QDir::cleanPath(homeDir + "/.myapps/" + m_currentUsername + "/tmp");

        QString targetPath;
        QString fileId = reply->property("fileId").toString();
        
        // 如果提供了文件ID，从数据库获取文件夹路径和文件名
        if (!fileId.isEmpty() && m_databaseManager) {
            // 查询文件信息
            KmsFile kmsFile = m_databaseManager->queryFileById(fileId);
            if (!kmsFile.id.isEmpty()) {
                QString fileName = kmsFile.name;
                QString folderId = kmsFile.folderId;
                
                // 查询文件夹信息获取路径
                QString folderPath = "";
                if (!folderId.isEmpty()) {
                    KmsFolder folder = m_databaseManager->queryFolderById(folderId);
                    if (!folder.id.isEmpty()) {
                        folderPath = folder.path;
                    }
                }
                
                // 构建目标路径: workBase + folderPath + fileName
                if (!folderPath.isEmpty()) {
                    // 清理路径：移除开头的斜杠
                    if (folderPath.startsWith('/')) {
                        folderPath.remove(0, 1);
                    }
                    targetPath = QDir::cleanPath(workBase + "/" + folderPath + "/" + fileName);
                } else {
                    // 如果没有文件夹路径，只使用文件名
                    targetPath = QDir::cleanPath(workBase + "/" + fileName);
                }
                
                qDebug() << "使用数据库路径，文件夹路径:" << folderPath << "文件名:" << fileName;
            }
        }
        
        // 如果无法从数据库获取路径，则使用原有的相对URL方式
        if (targetPath.isEmpty()) {
            // 使用相对URL作为目录结构（包含文件名）
            QString relativeUrl = reply->property("fileRelativeUrl").toString();
            if (relativeUrl.startsWith('/')) {
                relativeUrl.remove(0, 1);
            }

            // 如果未提供相对URL，则回退到从实际请求URL解析文件名
            if (relativeUrl.isEmpty()) {
                QString fileName = reply->property("fileName").toString();
                if (fileName.isEmpty()) {
                    QUrl reqUrl = reply->url();
                    fileName = QFileInfo(reqUrl.path()).fileName();
                    if (fileName.isEmpty()) {
                        fileName = "downloaded_file";
                    }
                }
                relativeUrl = fileName;
            }

            targetPath = QDir::cleanPath(workBase + "/" + relativeUrl);
            qDebug() << "使用相对URL路径:" << relativeUrl;
        }

        // 先保存到临时目录
        QString tmpDir = QDir::cleanPath(tempBase);
        if (!QDir().mkpath(tmpDir)) {
            qDebug() << "创建临时目录失败:" << tmpDir;
            emit downloadFileCompleted(-2, "无法创建临时目录: " + tmpDir, "");
            return;
        }

        // 生成临时文件名（使用文件ID或随机名称）
        QString tmpFileName;
        if (!fileId.isEmpty()) {
            tmpFileName = fileId + ".tmp";
        } else {
            tmpFileName = QString("download_%1_%2.tmp")
                             .arg(QDateTime::currentMSecsSinceEpoch())
                             .arg(QRandomGenerator::global()->bounded(100000));
        }
        QString tmpFilePath = QDir::cleanPath(tmpDir + "/" + tmpFileName);

        // 保存文件到临时目录
        QFile tmpFile(tmpFilePath);
        if (!tmpFile.open(QIODevice::WriteOnly)) {
            qDebug() << "无法创建临时文件:" << tmpFilePath << "错误:" << tmpFile.errorString();
            emit downloadFileCompleted(-2, "无法创建临时文件: " + tmpFile.errorString(), "");
            return;
        }

        qint64 bytesWritten = tmpFile.write(data);
        tmpFile.close();
        
        if (bytesWritten != data.size()) {
            qDebug() << "文件写入失败，写入字节数不匹配，期望:" << data.size() << "实际:" << bytesWritten;
            // 删除临时文件
            tmpFile.remove();
            emit downloadFileCompleted(-3, "文件保存失败，写入字节数不匹配", "");
            return;
        }

        qDebug() << "文件已保存到临时目录:" << tmpFilePath;

        // 确保目标目录存在
        QFileInfo targetInfo(targetPath);
        if (!QDir().mkpath(targetInfo.path())) {
            qDebug() << "创建目标目录失败:" << targetInfo.path();
            // 删除临时文件
            tmpFile.remove();
            emit downloadFileCompleted(-2, "无法创建目录: " + targetInfo.path(), "");
            return;
        }

        // 如果目标文件已存在，先删除（确保移动操作成功）
        if (QFile::exists(targetPath)) {
            if (!QFile::remove(targetPath)) {
                qDebug() << "无法删除已存在的目标文件:" << targetPath;
                // 删除临时文件
                tmpFile.remove();
                emit downloadFileCompleted(-2, "无法删除已存在的目标文件", "");
                return;
            }
        }

        // 从临时目录移动到最终位置
        if (!QFile::rename(tmpFilePath, targetPath)) {
            qDebug() << "移动文件失败，从:" << tmpFilePath << "到:" << targetPath;
            // 删除临时文件
            tmpFile.remove();
            emit downloadFileCompleted(-2, "无法移动文件到目标位置", "");
            return;
        }

        qDebug() << "文件移动成功，最终路径:" << targetPath;

        // 计算相对于工作目录的路径并更新到数据库
        if (!fileId.isEmpty() && m_databaseManager) {
            QDir workDir(workBase);
            QString relativePath = workDir.relativeFilePath(targetPath);
            // 将路径分隔符统一为正斜杠（用于跨平台兼容）
            relativePath = relativePath.replace('\\', '/');
            
            // 更新本地文件信息（包括相对路径）
            QFileInfo fileInfo(targetPath);
            qint64 fileSize = fileInfo.size();
            
            // 这里可以计算文件校验和，暂时使用空字符串
            QString checksum;
            m_databaseManager->updateLocalFileInfo(fileId, fileSize, checksum, relativePath);
            
            // 更新文件状态为已同步(1)
            m_databaseManager->updateFileStatus(fileId, 1);
            
            qDebug() << "已更新数据库，文件ID:" << fileId << "相对路径:" << relativePath << "状态已更新为1";
        }

        emit downloadFileCompleted(0, "文件下载成功", targetPath);
    } else {
        qDebug() << "下载文件失败:" << reply->errorString();
        emit downloadFileCompleted(reply->error(), "下载失败: " + reply->errorString(), "");
    }
}

void BackendService::handleRollbackFileResponse(QNetworkReply *reply)
{
    if (!reply) {
        qDebug() << "回撤文件响应为空";
        emit rollbackFileCompleted(-1, "回撤响应为空");
        return;
    }
    
    qDebug() << "处理回撤文件响应，错误:" << reply->error();
    
    if (reply->error() == QNetworkReply::NoError) {
        // 获取文件信息成功
        QByteArray data = reply->readAll();
        qDebug() << "获取文件信息成功，数据大小:" << data.size() << "字节";
        
        // 解析JSON响应
        QJsonParseError parseError;
        QJsonDocument doc = QJsonDocument::fromJson(data, &parseError);
        
        if (parseError.error != QJsonParseError::NoError) {
            qDebug() << "回撤文件JSON解析错误:" << parseError.errorString();
            emit rollbackFileCompleted(-1, "JSON解析失败: " + parseError.errorString());
            return;
        }
        
        if (!doc.isObject()) {
            qDebug() << "回撤文件响应不是有效的JSON对象";
            emit rollbackFileCompleted(-1, "响应格式错误");
            return;
        }
        
        QJsonObject response = doc.object();
        int errcode = response["errcode"].toInt();
        QString errmsg = response["errmsg"].toString();
        
        if (errcode == 0) {
            // 成功获取文件信息
            QJsonObject fileData = response["data"].toObject();
            qDebug() << "获取文件信息成功:" << errmsg;
            qDebug() << "文件信息:" << fileData;
            
            // 更新数据库中的文件信息
            if (m_databaseManager) {
                // 更新数据库中的文件信息
                bool updateSuccess = m_databaseManager->updateFileFromJson(fileData);
                if (updateSuccess) {
                    qDebug() << "数据库文件信息更新成功";
                    
                    // 获取文件URL并重新下载
                    QString fileUrl = fileData["url"].toString();
                    // 从reply属性中获取文件ID
                    QString fileId = reply->property("fileId").toString();
                    // 如果没有，尝试从fileData中获取
                    if (fileId.isEmpty()) {
                        fileId = fileData["id"].toString();
                    }
                    
                    if (!fileUrl.isEmpty()) {
                        qDebug() << "开始重新下载文件，URL:" << fileUrl << "文件ID:" << fileId;
                        if (!fileId.isEmpty()) {
                            // 获取文件名（从fileData或数据库中）
                            QString fileName = fileData["name"].toString();
                            if (fileName.isEmpty() && m_databaseManager) {
                                KmsFile kmsFile = m_databaseManager->queryFileById(fileId);
                                fileName = kmsFile.name;
                            }
                            downloadFile(fileUrl, fileName, fileId);
                        } else {
                            // 如果没有文件ID，只传递URL（不推荐，但为了兼容性保留）
                            qDebug() << "警告：没有文件ID，使用URL下载";
                            downloadFile(fileUrl);
                        }
                        emit rollbackFileCompleted(0, "文件信息更新成功，开始重新下载");
                    } else {
                        qDebug() << "文件信息中没有URL字段";
                        emit rollbackFileCompleted(-1, "文件信息中没有URL字段");
                    }
                } else {
                    qDebug() << "数据库文件信息更新失败";
                    emit rollbackFileCompleted(-1, "数据库文件信息更新失败");
                }
            } else {
                qDebug() << "数据库管理器未设置";
                emit rollbackFileCompleted(-1, "数据库管理器未设置");
            }
        } else {
            qDebug() << "获取文件信息失败:" << errmsg;
            emit rollbackFileCompleted(errcode, errmsg);
        }
    } else {
        qDebug() << "回撤文件失败:" << reply->errorString();
        emit rollbackFileCompleted(reply->error(), "回撤失败: " + reply->errorString());
    }
}

void BackendService::openFile(const QString &filePath)
{
    qDebug() << "准备打开文件:" << filePath;
    
    // 检查文件是否存在
    QFileInfo fileInfo(filePath);
    if (!fileInfo.exists()) {
        qDebug() << "文件不存在:" << filePath;
        emit openFileCompleted(-1, "文件不存在: " + filePath);
        return;
    }
    
    if (!fileInfo.isFile()) {
        qDebug() << "路径不是文件:" << filePath;
        emit openFileCompleted(-2, "路径不是文件: " + filePath);
        return;
    }
    
    // 使用 QDesktopServices 打开文件
    QUrl fileUrl = QUrl::fromLocalFile(filePath);
    bool success = QDesktopServices::openUrl(fileUrl);
    
    if (success) {
        qDebug() << "成功打开文件:" << filePath;
        emit openFileCompleted(0, "文件打开成功");
    } else {
        qDebug() << "打开文件失败:" << filePath;
        emit openFileCompleted(-3, "无法打开文件，可能没有关联的应用程序");
    }
}

void BackendService::openFileByURL(const QString &downloadUrl, const QString &accessToken)
{
    qDebug() << "准备通过URL下载并打开文件，URL:" << downloadUrl;
    
    // 验证URL
    if (downloadUrl.isEmpty()) {
        qDebug() << "下载URL为空";
        emit openFileCompleted(-1, "下载URL为空");
        return;
    }
    
    // 验证URL格式
    QUrl url(downloadUrl);
    if (!url.isValid()) {
        qDebug() << "无效的URL:" << downloadUrl;
        emit openFileCompleted(-1, "无效的URL: " + downloadUrl);
        return;
    }
    
    qDebug() << "开始下载文件，URL:" << downloadUrl;
    
    // 创建网络请求
    QNetworkRequest request;
    request.setUrl(url);
    
    // 添加token到请求头
    if (!accessToken.isEmpty()) {
        // 如果传入了 accessToken 参数，使用传入的 token
        request.setRawHeader("accessToken", accessToken.toUtf8());
        qDebug() << "已添加传入的accessToken到请求头";
    } else {
        // 否则使用内部的 token
        addTokenToRequest(request);
    }
    
    // 发送GET请求
    QNetworkReply *reply = m_networkManager->get(request);
    qDebug() << "发送下载文件请求，reply对象:" << reply;
    
    // 设置用户数据，用于识别请求类型
    reply->setProperty("requestType", "downloadFileByURL");
    
    // 保存原始URL
    reply->setProperty("downloadUrl", downloadUrl);
    
    // 连接下载进度信号
    connect(reply, &QNetworkReply::downloadProgress, this, [this](qint64 bytesReceived, qint64 bytesTotal) {
        emit downloadProgress(bytesReceived, bytesTotal);
    });
}

void BackendService::handleDownloadFileByURLResponse(QNetworkReply *reply)
{
    if (!reply) {
        qDebug() << "下载文件响应为空";
        emit openFileCompleted(-1, "下载响应为空");
        return;
    }
    
    qDebug() << "处理通过URL下载文件响应，错误:" << reply->error();
    
    if (reply->error() == QNetworkReply::NoError) {
        // 下载成功，保存文件
        QByteArray data = reply->readAll();
        qDebug() << "下载文件成功，数据大小:" << data.size() << "字节";
        
        // 获取临时目录
        const QString homeDir = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
        
        // 构建runtime目录路径（使用临时目录）
        QString runtimeDir = QDir::cleanPath(homeDir + "/.myapps/" + "/runtime");
        
        // 确保runtime目录存在
        if (!QDir().mkpath(runtimeDir)) {
            qDebug() << "创建runtime目录失败:" << runtimeDir;
            emit openFileCompleted(-2, "无法创建runtime目录: " + runtimeDir);
            return;
        }
        
        // 从响应头的Content-Disposition中提取文件名
        QString fileName;
        QString contentDisposition = reply->rawHeader("Content-Disposition").constData();
        if (!contentDisposition.isEmpty()) {
            // 解析Content-Disposition: attachment; filename="xxx" 或 filename*=UTF-8''xxx
            QRegularExpression rx("filename\\*?=['\"]?([^'\"\\s;]+)['\"]?");
            QRegularExpressionMatch match = rx.match(contentDisposition);
            if (match.hasMatch()) {
                fileName = match.captured(1);
                // 处理URL编码的文件名（filename*=UTF-8''xxx格式）
                if (fileName.contains("UTF-8''")) {
                    fileName = fileName.mid(fileName.indexOf("UTF-8''") + 7);
                    fileName = QUrl::fromPercentEncoding(fileName.toUtf8());
                }
            } else {
                // 尝试另一种格式：filename="xxx"
                QRegularExpression rx2("filename=\"?([^\";]+)\"?");
                QRegularExpressionMatch match2 = rx2.match(contentDisposition);
                if (match2.hasMatch()) {
                    fileName = match2.captured(1);
                }
            }
        }
        
        // 如果从Content-Disposition中无法获取文件名，尝试从URL中提取
        if (fileName.isEmpty()) {
            QString downloadUrl = reply->property("downloadUrl").toString();
            QUrl url(downloadUrl);
            fileName = QFileInfo(url.path()).fileName();
            // 处理URL参数中的filename（如果有）
            if (fileName.isEmpty() || fileName == "/") {
                QUrlQuery query(url);
                fileName = query.queryItemValue("filename");
            }
        }
        
        // 如果仍然没有文件名，使用时间戳生成
        if (fileName.isEmpty()) {
            fileName = QString("downloaded_file_%1").arg(QDateTime::currentMSecsSinceEpoch());
        }
        
        // 构建目标文件路径
        QString targetPath = QDir::cleanPath(runtimeDir + "/" + fileName);
        
        // 如果文件已存在，添加时间戳后缀
        if (QFile::exists(targetPath)) {
            QFileInfo fileInfo(targetPath);
            QString baseName = fileInfo.baseName();
            QString suffix = fileInfo.completeSuffix();
            QString newFileName = QString("%1_%2.%3")
                                  .arg(baseName)
                                  .arg(QDateTime::currentMSecsSinceEpoch())
                                  .arg(suffix.isEmpty() ? "tmp" : suffix);
            targetPath = QDir::cleanPath(runtimeDir + "/" + newFileName);
        }
        
        qDebug() << "保存文件到:" << targetPath;
        
        // 保存文件
        QFile file(targetPath);
        if (!file.open(QIODevice::WriteOnly)) {
            qDebug() << "无法创建文件:" << targetPath << "错误:" << file.errorString();
            emit openFileCompleted(-2, "无法创建文件: " + file.errorString());
            return;
        }
        
        qint64 bytesWritten = file.write(data);
        file.close();
        
        if (bytesWritten != data.size()) {
            qDebug() << "文件写入失败，写入字节数不匹配，期望:" << data.size() << "实际:" << bytesWritten;
            file.remove();
            emit openFileCompleted(-3, "文件保存失败，写入字节数不匹配");
            return;
        }
        
        qDebug() << "文件已成功保存到:" << targetPath;
        
        // 更新 kms_command 表的 LOCAL_FILE_PATH 字段
        if (m_databaseManager) {
            QString downloadUrl = reply->property("downloadUrl").toString();
            if (!downloadUrl.isEmpty()) {
                // 使用绝对路径作为 LOCAL_FILE_PATH
                // 因为 runtime 目录是临时目录，使用绝对路径更合适
                if (m_databaseManager->updateCommandLocalFilePath(downloadUrl, targetPath)) {
                    qDebug() << "成功更新命令记录LOCAL_FILE_PATH，URL:" << downloadUrl << "路径:" << targetPath;
                } else {
                    qDebug() << "更新命令记录LOCAL_FILE_PATH失败，URL:" << downloadUrl;
                }
            }
        }
        
        // 下载完成后，调用openFile打开文件
        openFile(targetPath);
    } else {
        qDebug() << "下载文件失败:" << reply->errorString();
        emit openFileCompleted(-1, "下载失败: " + reply->errorString());
    }
}

void BackendService::openFileByFileId(const QString &fileId)
{
    qDebug() << "准备根据文件ID打开文件，文件ID:" << fileId;
    
    // 验证文件ID
    if (fileId.isEmpty()) {
        qDebug() << "文件ID为空";
        emit openFileCompleted(-1, "文件ID为空");
        return;
    }
    
    // 检查数据库管理器是否设置
    if (!m_databaseManager) {
        qDebug() << "数据库管理器未设置";
        emit openFileCompleted(-1, "数据库管理器未设置");
        return;
    }
    
    // 查询文件信息
    KmsFile kmsFile = m_databaseManager->queryFileById(fileId);
    if (kmsFile.id.isEmpty()) {
        qDebug() << "未找到文件记录，文件ID:" << fileId;
        
        // 补充：如果未找到文件记录，则通过 getKmsFileByFileId 接口获取文件信息
        // 使用一次性信号连接来处理异步响应
        QMetaObject::Connection *connection = new QMetaObject::Connection();
        *connection = connect(this, &BackendService::getKmsFileByFileIdCompleted,
                              [this, fileId, connection](int resultCode, const QString &message, const QVariantMap &fileData) {
            // 断开一次性连接
            disconnect(*connection);
            delete connection;
            
            if (resultCode == 0 && !fileData.isEmpty()) {
                // 将QVariantMap转换为KmsFile
                KmsFile kmsFile = convertVariantMapToKmsFile(fileData);
                
                // 插入数据库
                if (m_databaseManager && m_databaseManager->insertFile(kmsFile)) {
                    qDebug() << "插入文件记录成功，文件ID:" << kmsFile.id;
                    
                    // 检查文件是否需要下载（如果是文件夹或文件URL为空，可能需要特殊处理）
                    // 这里先尝试继续打开文件的流程
                    doOpenFileWithKmsFile(kmsFile);
                } else {
                    qDebug() << "插入文件记录失败";
                    emit openFileCompleted(-1, "插入文件记录失败");
                }
            } else {
                qDebug() << "获取文件信息失败:" << message;
                emit openFileCompleted(resultCode, message);
            }
        });
        
        // 调用API获取文件信息
        getKmsFileByFileId(fileId);
        return; // 异步操作，等待信号响应
    }
    
    // 找到了文件记录，执行打开文件的操作
    doOpenFileWithKmsFile(kmsFile);
}

void BackendService::doOpenFileWithKmsFile(const KmsFile &kmsFile)
{
    qDebug() << "找到文件记录，文件名:" << kmsFile.name << "本地路径:" << kmsFile.localFilePath;
    
    // 构建完整的本地文件路径
    QString workBase = getUserWorkBaseDir();
    QString localFilePath;
    
    // 优先使用 localFilePath 字段（相对于工作目录的路径）
    if (!kmsFile.localFilePath.isEmpty()) {
        localFilePath = QDir::cleanPath(workBase + "/" + kmsFile.localFilePath);
        qDebug() << "使用 localFilePath 字段构建本地路径";
    } else {
        // 如果 localFilePath 为空，回退到根据文件夹路径和文件名构建
        // 从数据库获取文件夹路径
        QString folderPath = "";
        if (!kmsFile.folderId.isEmpty() && m_databaseManager) {
            // 通过查询文件夹路径来获取（使用PATH字段查询）
            QList<KmsFolder> allFolders = m_databaseManager->queryAllFolders();
            for (const auto &folder : allFolders) {
                if (folder.id == kmsFile.folderId) {
                    folderPath = folder.path;
                    break;
                }
            }
        }
        
        // 构建路径
        if (!folderPath.isEmpty()) {
            // 清理路径：移除开头的斜杠
            QString cleanFolderPath = folderPath;
            if (cleanFolderPath.startsWith('/')) {
                cleanFolderPath.remove(0, 1);
            }
            localFilePath = QDir::cleanPath(workBase + "/" + cleanFolderPath + "/" + kmsFile.name);
        } else {
            // 如果没有文件夹路径，只使用文件名
            localFilePath = QDir::cleanPath(workBase + "/" + kmsFile.name);
        }
        qDebug() << "回退到根据文件夹路径和文件名构建本地路径";
    }
    
    qDebug() << "构建的本地文件路径:" << localFilePath;
    
    // 检查文件是否存在
    QFileInfo fileInfo(localFilePath);
    if (!fileInfo.exists()) {
        qDebug() << "文件不存在:" << localFilePath;
        qDebug() << "文件不存在，先下载文件，文件ID:" << kmsFile.id;
        
        // 使用一次性信号连接来处理下载完成后的打开操作
        QMetaObject::Connection *connection = new QMetaObject::Connection();
        *connection = connect(this, &BackendService::downloadFileCompleted,
                              [this, localFilePath, connection](int resultCode, const QString &message, const QString &filePath) {
            // 断开一次性连接
            disconnect(*connection);
            delete connection;
            
            if (resultCode == 0) {
                // 下载成功，打开文件
                // 使用下载后的文件路径（如果提供了），否则使用之前构建的路径
                QString finalPath = filePath.isEmpty() ? localFilePath : filePath;
                qDebug() << "文件下载成功，准备打开文件:" << finalPath;
                openFile(finalPath);
            } else {
                // 下载失败，发送错误信号
                qDebug() << "文件下载失败:" << message;
                emit openFileCompleted(resultCode, "文件下载失败: " + message);
            }
        });
        
        // 开始下载文件
        downloadFile("", kmsFile.name, kmsFile.id);
        return; // 异步操作，等待下载完成
    }
    
    // 文件存在，直接打开
    qDebug() << "准备打开文件:" << localFilePath;
    openFile(localFilePath);
}

KmsFile BackendService::convertVariantMapToKmsFile(const QVariantMap &fileMap)
{
    KmsFile kmsFile;
    
    // 基本字段
    kmsFile.id = fileMap["id"].toString();
    kmsFile.name = fileMap["name"].toString();
    kmsFile.diskId = fileMap["diskId"].toString();
    kmsFile.folderId = fileMap["folderId"].toString();
    kmsFile.creator = fileMap["creator"].toString();
    kmsFile.creatorId = fileMap["creatorId"].toString();
    
    // 日期字段
    kmsFile.createDate = fileMap["createDate"].toString();
    kmsFile.lastModifyDate = fileMap["lastModifyDate"].toString();
    
    // 类型字段 - API返回的是int，但KmsFile.type是QString，需要转换
    int typeInt = fileMap["type"].toInt();
    kmsFile.type = QString::number(typeInt);
    
    // 数值字段
    kmsFile.size = fileMap["size"].toLongLong();
    
    // 可选字段
    kmsFile.removeOperator = fileMap["removeOperator"].toString();
    
    // 默认值字段
    kmsFile.originType = 0;
    kmsFile.originId = "";
    kmsFile.status = fileMap["delete"].toBool() ? -1 : 1; // 如果delete为true，状态为-1（标记删除），否则为1（已同步）
    kmsFile.checksum = "";
    kmsFile.localFileSize = 0;
    kmsFile.localFileChecksum = "";
    kmsFile.localFilePath = "";
    
    return kmsFile;
}

QString BackendService::getUserWorkBaseDir() const
{
    // Home/.myapps/{username}/work
    const QString homeDir = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
    return QDir::cleanPath(homeDir + "/.myapps/" + m_currentUsername + "/work");
}

void BackendService::getApplications()
{
    qDebug() << "BackendService: 开始获取应用列表";
    QString url = m_baseUrl + "/obpm/api/runtime/applications";
    QNetworkRequest request = createRequest(url, "GET");
    addTokenToRequest(request);
    request.setAttribute(QNetworkRequest::User, "getApplications");
    QNetworkReply *reply = m_networkManager->get(request);
    if (reply) {
        reply->setProperty("requestType", "getApplications");
    }
    qDebug() << "BackendService: 发送获取应用列表请求到" << url;
}

void BackendService::getNotice(int readStatus, int type, int currpage, int rowcount)
{
    qDebug() << "BackendService: 开始获取通知消息";
    qDebug() << "参数 - readStatus:" << readStatus << "type:" << type 
             << "currpage:" << currpage << "rowcount:" << rowcount;
    
    // 构建请求URL
    QString url = m_baseUrl + "/message/api/message/notice";
    QString queryParams = buildQueryParams(readStatus, type, currpage, rowcount);
    if (!queryParams.isEmpty()) {
        url += "?" + queryParams;
    }
    
    QNetworkRequest request = createRequest(url, "GET");
    
    // 添加访问令牌到请求头
    addTokenToRequest(request);
    
    // 设置请求属性，用于识别请求类型
    request.setAttribute(QNetworkRequest::User, "getNotice");
    
    // 发送GET请求
    QNetworkReply *reply = m_networkManager->get(request);
    if (!reply) {
        qDebug() << "BackendService: 创建网络请求失败";
        emit networkError(-1, "创建网络请求失败");
        return;
    }
    
    // 设置请求类型属性
    reply->setProperty("requestType", "getNotice");
    
    qDebug() << "BackendService: 已发送获取通知消息请求到" << url;
}

void BackendService::markReadNotice(const QString &noticeId)
{
    qDebug() << "BackendService: 开始标记通知为已读，通知ID:" << noticeId;
    
    if (noticeId.isEmpty()) {
        qDebug() << "BackendService: 通知ID为空";
        emit markReadNoticeCompleted(-1, "通知ID为空", noticeId);
        return;
    }
    
    // 构建请求URL
    QString url = m_baseUrl + "/message/api/message/notice/read?noticeId=" + noticeId;
    QNetworkRequest request = createRequest(url, "PUT");
    
    // 添加访问令牌到请求头
    addTokenToRequest(request);
    
    // 设置请求属性，用于识别请求类型
    request.setAttribute(QNetworkRequest::User, "markReadNotice");
    
    // 发送PUT请求
    QNetworkReply *reply = m_networkManager->put(request, QByteArray());
    if (!reply) {
        qDebug() << "BackendService: 创建网络请求失败";
        emit networkError(-1, "创建网络请求失败");
        return;
    }
    
    // 设置请求类型属性和通知ID
    reply->setProperty("requestType", "markReadNotice");
    reply->setProperty("noticeId", noticeId);
    
    qDebug() << "BackendService: 已发送标记已读请求到" << url;
}

void BackendService::handleCommitFileResponse(QNetworkReply *reply)
{
    qDebug() << "处理文件提交响应，reply对象:" << reply;
    
    // 检查是否已经处理过这个响应
    if (reply->property("processed").toBool()) {
        qDebug() << "响应已经被处理过，跳过";
        return;
    }
    
    // 标记为已处理
    reply->setProperty("processed", true);
    
    if (reply->error() == QNetworkReply::NoError) {
        QByteArray data = reply->readAll();
        qDebug() << "文件提交响应原始数据长度:" << data.length();
        qDebug() << "文件提交响应原始数据:" << data;
        
        QJsonDocument doc = QJsonDocument::fromJson(data);
        QJsonObject response = doc.object();
        
        qDebug() << "文件提交响应:" << response;
        
        parseCommitFileResponse(response);
    } else {
        qDebug() << "文件提交失败:" << reply->errorString();
        emit commitFileCompleted(reply->error(), "提交失败: " + reply->errorString());
    }
}

void BackendService::parseCommitFileResponse(const QJsonObject &response)
{
    // 添加完整的响应数据日志
    qDebug() << "文件提交响应完整数据:" << response;
    qDebug() << "文件提交响应键列表:" << response.keys();
    
    int errcode = response["errcode"].toInt();
    QString errmsg = response["errmsg"].toString();
    
    qDebug() << "文件提交响应 - errcode:" << errcode << "errmsg:" << errmsg;
    
    if (errcode == 0) {
        qDebug() << "文件提交成功:" << errmsg;
        
        // 更新文件状态为已同步(1)
        if (!m_currentCommitSourceFileId.isEmpty()) {
            qDebug() << "文件提交成功，更新文件状态，文件ID:" << m_currentCommitSourceFileId;
            emit commitFileSuccess(m_currentCommitSourceFileId);
            m_currentCommitSourceFileId.clear(); // 清除当前提交的文件ID
        }
        
        // 检查是否有data字段
        if (response.contains("data")) {
            qDebug() << "文件提交 - 找到data字段，类型:" << response["data"].type();
            if (response["data"].isArray()) {
                QJsonArray dataArray = response["data"].toArray();
                qDebug() << "文件提交 - 返回数据数量:" << dataArray.size();
                qDebug() << "文件提交 - 返回数据内容:" << dataArray;
                
                // 发送提交数据信号，用于更新数据库
                emit commitFileData(dataArray);
                
                // 发送提交完成信号
                emit commitFileCompleted(0, "文件提交成功，共" + QString::number(dataArray.size()) + "个文件");
            } else {
                qDebug() << "文件提交 - data字段不是数组，实际类型:" << response["data"].type();
                qDebug() << "文件提交 - data字段内容:" << response["data"];
                emit commitFileCompleted(-4, "响应数据格式错误：data字段不是数组");
            }
        } else {
            qDebug() << "文件提交 - 响应中没有data字段";
            qDebug() << "文件提交 - 可用字段:" << response.keys();
            emit commitFileCompleted(-4, "响应数据格式错误：缺少data字段");
        }
    } else {
        qDebug() << "文件提交失败:" << errmsg;
        emit commitFileCompleted(errcode, errmsg);
    }
}

void BackendService::handleGetApplicationsResponse(QNetworkReply *reply)
{
    qDebug() << "BackendService: 处理获取应用列表响应";
    
    // 检查网络错误
    if (reply->error() != QNetworkReply::NoError) {
        qDebug() << "BackendService: 网络错误 - 代码:" << reply->error() << "描述:" << reply->errorString();
        emit getApplicationsCompleted(-1, "网络错误: " + reply->errorString(), QVariantList());
        return;
    }
    
    // 读取响应数据
    QByteArray responseData = reply->readAll();
    qDebug() << "BackendService: 收到响应数据长度:" << responseData.size();
    qDebug() << "BackendService: 响应数据内容:" << responseData;
    
    // 解析JSON响应
    QJsonParseError parseError;
    QJsonDocument doc = QJsonDocument::fromJson(responseData, &parseError);
    
    if (parseError.error != QJsonParseError::NoError) {
        qDebug() << "BackendService: JSON解析错误:" << parseError.errorString();
        emit getApplicationsCompleted(-2, "响应数据格式错误", QVariantList());
        return;
    }
    
    if (!doc.isObject()) {
        qDebug() << "BackendService: 响应数据不是有效的JSON对象";
        emit getApplicationsCompleted(-3, "响应数据格式错误", QVariantList());
        return;
    }
    
    QJsonObject response = doc.object();
    parseGetApplicationsResponse(response);
}

void BackendService::parseGetApplicationsResponse(const QJsonObject &response)
{
    qDebug() << "BackendService: 解析获取应用列表响应";
    qDebug() << "BackendService: 完整响应对象:" << response;
    
    // 解析响应字段
    int resultCode = response["errcode"].toInt();
    QString message = response["errmsg"].toString();
    QVariantList applications;
    
    qDebug() << "BackendService: 响应结果码:" << resultCode << "消息:" << message;
    
    if (resultCode == 0) {
        if (response.contains("data")) {
            QJsonValue dataValue = response["data"];
            if (dataValue.isObject()) {
                QJsonObject dataObj = dataValue.toObject();
                qDebug() << "BackendService: data字段是对象，键列表:" << dataObj.keys();
                
                if (dataObj.contains("applications") && dataObj["applications"].isArray()) {
                    QJsonArray applicationsArray = dataObj["applications"].toArray();
                    qDebug() << "BackendService: 找到applications数组，数量:" << applicationsArray.size();
                    
                    for (const QJsonValue &value : applicationsArray) {
                        if (value.isObject()) {
                            QJsonObject appObj = value.toObject();
                            QVariantMap appMap;
                            for (auto it = appObj.begin(); it != appObj.end(); ++it) {
                                appMap[it.key()] = it.value().toVariant();
                            }
                            applications.append(appMap);
                        }
                    }
                    qDebug() << "BackendService: 解析到" << applications.size() << "个应用";
                } else {
                    qDebug() << "BackendService: data对象中没有applications数组";
                }
            } else {
                qDebug() << "BackendService: data字段不是对象";
            }
        } else {
            qDebug() << "BackendService: 响应中没有data字段";
        }
    } else {
        qDebug() << "BackendService: 服务器返回错误代码:" << resultCode << "消息:" << message;
    }
    
    // 发送完成信号
    emit getApplicationsCompleted(resultCode, message, applications);
}

void BackendService::handleGetNoticeResponse(QNetworkReply *reply)
{
    qDebug() << "BackendService: 处理获取通知消息响应";
    
    // 检查网络错误
    if (reply->error() != QNetworkReply::NoError) {
        handleNetworkError(reply);
        return;
    }
    
    // 读取响应数据
    QByteArray data = reply->readAll();
    qDebug() << "BackendService: 收到响应数据长度:" << data.length();
    
    // 解析JSON响应
    QJsonParseError parseError;
    QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &parseError);
    
    if (parseError.error != QJsonParseError::NoError) {
        qDebug() << "BackendService: JSON解析错误:" << parseError.errorString();
        emit getNoticeCompleted(-1, "JSON解析错误: " + parseError.errorString(), QVariantList());
        return;
    }
    
    if (!jsonDoc.isObject()) {
        qDebug() << "BackendService: 响应不是有效的JSON对象";
        emit getNoticeCompleted(-1, "响应不是有效的JSON对象", QVariantList());
        return;
    }
    
    QJsonObject response = jsonDoc.object();
    parseGetNoticeResponse(response);
}

void BackendService::parseGetNoticeResponse(const QJsonObject &response)
{
    qDebug() << "BackendService: 解析获取通知消息响应";
    
    // 检查响应状态
    int resultCode = 0;
    QString message = "成功";
    QVariantList notices;
    
    // 检查是否有错误信息
    if (response.contains("error")) {
        resultCode = -1;
        message = response["error"].toString();
        qDebug() << "BackendService: 服务器返回错误:" << message;
    } else if (response.contains("code")) {
        resultCode = response["code"].toInt();
        if (resultCode != 0) {
            message = response.contains("message") ? response["message"].toString() : "未知错误";
            qDebug() << "BackendService: 服务器返回错误代码:" << resultCode << "消息:" << message;
        }
    }
    
    // 解析通知列表数据
    if (resultCode == 0) {
        if (response.contains("data")) {
            QJsonValue dataValue = response["data"];
            if (dataValue.isObject()) {
                QJsonObject dataObj = dataValue.toObject();
                qDebug() << "BackendService: data字段是对象，键列表:" << dataObj.keys();
                
                // 检查是否有datas数组
                if (dataObj.contains("datas") && dataObj["datas"].isArray()) {
                    QJsonArray datasArray = dataObj["datas"].toArray();
                    qDebug() << "BackendService: 找到datas数组，数量:" << datasArray.size();
                    
                    for (const QJsonValue &value : datasArray) {
                        if (value.isObject()) {
                            QJsonObject noticeObj = value.toObject();
                            QVariantMap noticeMap;
                            
                            // 将JSON对象转换为QVariantMap
                            for (auto it = noticeObj.begin(); it != noticeObj.end(); ++it) {
                                noticeMap[it.key()] = it.value().toVariant();
                            }
                            
                            notices.append(noticeMap);
                        }
                    }
                    qDebug() << "BackendService: 解析到" << notices.size() << "条通知";
                } else {
                    qDebug() << "BackendService: data对象中没有datas数组";
                }
            } else {
                qDebug() << "BackendService: data字段不是对象";
            }
        } else {
            qDebug() << "BackendService: 响应中没有data字段";
        }
    }
    
    // 发送完成信号
    emit getNoticeCompleted(resultCode, message, notices);
}

void BackendService::handleMarkReadNoticeResponse(QNetworkReply *reply)
{
    qDebug() << "BackendService: 处理标记已读响应";
    
    QString noticeId = reply->property("noticeId").toString();
    
    // 检查网络错误
    if (reply->error() != QNetworkReply::NoError) {
        handleNetworkError(reply);
        return;
    }
    
    // 读取响应数据
    QByteArray data = reply->readAll();
    qDebug() << "BackendService: 收到响应数据长度:" << data.length();
    
    // 解析JSON响应
    QJsonParseError parseError;
    QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &parseError);
    
    if (parseError.error != QJsonParseError::NoError) {
        qDebug() << "BackendService: JSON解析错误:" << parseError.errorString();
        emit markReadNoticeCompleted(-1, "JSON解析错误: " + parseError.errorString(), noticeId);
        return;
    }
    
    if (!jsonDoc.isObject()) {
        qDebug() << "BackendService: 响应不是有效的JSON对象";
        emit markReadNoticeCompleted(-1, "响应不是有效的JSON对象", noticeId);
        return;
    }
    
    QJsonObject response = jsonDoc.object();
    parseMarkReadNoticeResponse(response);
}

void BackendService::parseMarkReadNoticeResponse(const QJsonObject &response)
{
    qDebug() << "BackendService: 解析标记已读响应";
    
    // 检查响应状态
    int resultCode = 0;
    QString message = "成功";
    
    // 检查是否有错误信息
    if (response.contains("error")) {
        resultCode = -1;
        message = response["error"].toString();
        qDebug() << "BackendService: 服务器返回错误:" << message;
    } else if (response.contains("code")) {
        resultCode = response["code"].toInt();
        if (resultCode != 0) {
            message = response.contains("message") ? response["message"].toString() : "未知错误";
            qDebug() << "BackendService: 服务器返回错误代码:" << resultCode << "消息:" << message;
        }
    }
    
    // 发送完成信号
    emit markReadNoticeCompleted(resultCode, message, "");
}

QString BackendService::buildQueryParams(int readStatus, int type, int currpage, int rowcount)
{
    QUrlQuery query;
    
    // 只有当readStatus不为-1时才添加readStatus参数
    if (readStatus != -1) {
        query.addQueryItem("readStatus", QString::number(readStatus));
    }
    
    // 移除type参数，因为API不需要这个参数
    
    // 添加分页参数
    query.addQueryItem("_currpage", QString::number(currpage));
    query.addQueryItem("_rowcount", QString::number(rowcount));
    
    return query.toString();
}

void BackendService::handleNetworkError(QNetworkReply *reply)
{
    int errorCode = reply->error();
    QString errorString = reply->errorString();
    
    qDebug() << "BackendService: 网络错误 - 代码:" << errorCode << "描述:" << errorString;
    
    // 发送网络错误信号
    emit networkError(errorCode, errorString);
    
    // 根据请求类型发送相应的完成信号
    QString requestType = reply->property("requestType").toString();
    if (requestType == "getNotice") {
        emit getNoticeCompleted(errorCode, "网络错误: " + errorString, QVariantList());
    } else if (requestType == "markReadNotice") {
        QString noticeId = reply->property("noticeId").toString();
        emit markReadNoticeCompleted(errorCode, "网络错误: " + errorString, noticeId);
    }
}

QNetworkRequest BackendService::createRequest(const QString &url, const QString &method)
{
    QNetworkRequest request;
    request.setUrl(QUrl(url));
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
    request.setRawHeader("Accept", "application/json");
    request.setRawHeader("User-Agent", "BackendService/1.0");
    
    // 设置HTTP方法
    if (method.toUpper() == "POST") {
        request.setAttribute(QNetworkRequest::CustomVerbAttribute, "POST");
    } else if (method.toUpper() == "PUT") {
        request.setAttribute(QNetworkRequest::CustomVerbAttribute, "PUT");
    } else if (method.toUpper() == "DELETE") {
        request.setAttribute(QNetworkRequest::CustomVerbAttribute, "DELETE");
    }
    
    return request;
}
